Может ли SQL Server SQL_Latin1_General_CP1_CI_AS безопасно конвертироваться в Latin1_General_CI_AS? - PullRequest
22 голосов
/ 09 июня 2011

У нас есть устаревшая база данных с некоторыми (более старыми) столбцами, использующими «SQL_Latin1_General_CP1_CI_AS», а более поздние изменения использовали «Latin1_General_CI_AS».

Это неприятно, поскольку для работы объединений требуется дополнительный оператор COLLATE.

Я бы хотел довести все до "Latin1_General_CI_AS". Из того, что я могу извлечь, это более или менее идентичные сопоставления, и я не потеряю данные во время этого процесса ...

Кто-нибудь знает, так ли это?

Ответы [ 5 ]

30 голосов
/ 27 февраля 2014

Вот более полный ответ:

https://www.olcot.co.uk/revised-difference-between-collation-sql_latin1_general_cp1_ci_as-and-latin1_general_ci_as/

Ключевое различие между этими параметрами сортировки заключается в том, как они применяют правила расширения символов. Некоторые латинские символы могут быть расширены до нескольких символов. Параметры сортировки SQL_xxxx могут игнорировать эти расширения символов при работе с текстом, не относящимся к Юникоду, но применять их к тексту Юникода. В результате: объединения, сортировки и сравнения могут давать разные результаты при использовании одного сопоставления против другого.

Пример:

В Latin1_General_CI_AS эти два оператора возвращают один и тот же набор записей, так как ß расширен до ss.

SELECT * FROM MyTable3 WHERE Comments = 'strasse'
SELECT * FROM MyTable3 WHERE Comments = 'straße'

При использовании SQL_Latin1_General_CP1_CI_AS приведенные выше операторы возвращают разные записи, поскольку ß рассматривается как символ, отличный от ss.

21 голосов
/ 17 декабря 2015

Если вы собираетесь изменить параметры сортировки базы данных, то, безусловно, есть вещи, о которых вы должны знать, чтобы вы могли планировать соответственно:

  • Относительно потери данных:

    • NVARCHAR все поля имеют Unicode, который является единым набором символов, поэтому не может быть никакой потери данных для этих полей (это также относится к полям XML, которые также хранятся как UTF-16 Little Endian). Все поля метаданных, в которых хранятся имена объектов / столбцов / индексов / и т. Д. NVARCHAR, поэтому не нужно беспокоиться об этом.
    • VARCHAR поля, имеющие разные сопоставления, но одну и ту же кодовую страницу между разными сопоставлениями не будут проблемой, поскольку кодовая страница является набором символов.
    • VARCHAR поля, имеющие разные параметры сортировки и перемещающиеся на другую кодовую страницу (при изменении параметров сортировки) могут иметь потерю данных, если какой-либо из используемых символов не представлен в новой кодовой странице. ОДНАКО, эта проблема возникает только при физическом изменении параметров сортировки определенного поля (описано ниже) и не возникает при изменении параметров сортировки базы данных по умолчанию.
  • Локальные переменные и строковые литералы получают свои параметры сортировки из базы данных по умолчанию. Изменение базы данных по умолчанию изменит сортировку, используемую как для локальных переменных, так и для строковых литералов. Но изменение параметров сортировки по умолчанию для базы данных не изменяет параметры сортировки, используемые для существующих строковых столбцов в таблицах в этой базе данных. Как правило, это не должно вызывать проблем при сравнении или объединении столбца с литералом и / или переменной, так как литералы и переменные будут принимать параметры сортировки столбца из-за приоритета сортировки. Единственной потенциальной проблемой могут быть преобразования кодовой страницы, которые могут произойти для символов со значениями от 128 до 255, которые недоступны в кодовой странице, используемой для сортировки столбца.

  • Если вы ожидаете, что предикат / сравнение / сортировка / конкатенация / и т. Д. Для столбца будут вести себя по-разному при изменении параметров сортировки по умолчанию для базы данных, то вам нужно будет явно изменить параметры сортировки этого столбца с помощью следующей команды:

    ALTER TABLE [{table_name}]
       ALTER COLUMN [{column_name}]
       {same_datatype}
       {same_NULL_or_NOT NULL_setting}
       COLLATE {name_of_Database_default_Collation};
    

    Обязательно укажите точно такой же тип данных и NULL / NOT NULL, которые используются в настоящее время, иначе они могут вернуться к значению по умолчанию, если оно еще не является значением по умолчанию. После этого, если есть какие-либо индексы в любом из строковых столбцов, которые только что изменили свои параметры сортировки, необходимо перестроить эти индексы.

  • Изменение параметров сортировки базы данных по умолчанию приведет к изменению параметров сортировки определенных метаданных, относящихся к базе данных, таких как поле name в обоих sys.objects, sys.columns, sys.indexes и т. Д. Фильтрация этих систем Представления против локальных переменных или строковых литералов не будут проблемой, так как сортировка будет изменяться с обеих сторон. Но если вы ПРИСОЕДИНЯЕТЕСЬ к любому из представлений локальной системы к временным таблицам на строковых полях, и сопоставление на уровне базы данных между локальной базой данных и tempdb не совпадает, то вы получите ошибку «Несоответствие сопоставления». Это обсуждается ниже вместе с лекарством.

  • Разница между этими двумя параметрами сортировки заключается в том, как они сортируют определенные символы для данных VARCHAR (это не влияет на данные NVARCHAR). Номера для сортировки не EBCDIC SQL_ используют так называемую «сортировку строк» ​​для данных VARCHAR, в то время как для всех других параметров сортировки и даже NVARCHAR для сортировок не EBCDIC SQL_ используется так называемая сортировка слов ». Разница в том, что в «Сортировке слов» тире - и апострофу ' (и, возможно, несколько других символов?) Даны очень малые веса и по существу игнорируются, если в строках нет других отличий. Чтобы увидеть это поведение в действии, выполните следующее:

    DECLARE @Test TABLE (Col1 VARCHAR(10) NOT NULL);
    INSERT INTO @Test VALUES ('aa');
    INSERT INTO @Test VALUES ('ac');
    INSERT INTO @Test VALUES ('ah');
    INSERT INTO @Test VALUES ('am');
    INSERT INTO @Test VALUES ('aka');
    INSERT INTO @Test VALUES ('akc');
    INSERT INTO @Test VALUES ('ar');
    INSERT INTO @Test VALUES ('a-f');
    INSERT INTO @Test VALUES ('a_e');
    INSERT INTO @Test VALUES ('a''kb');
    
    SELECT * FROM @Test ORDER BY [Col1] COLLATE SQL_Latin1_General_CP1_CI_AS;
    -- "String Sort" puts all punctuation ahead of letters
    
    SELECT * FROM @Test ORDER BY [Col1] COLLATE Latin1_General_100_CI_AS;
    -- "Word Sort" mostly ignores dash and apostrophe
    

    Возвращает:

    String Sort
    -----------
    a'kb
    a-f
    a_e
    aa
    ac
    ah
    aka
    akc
    am
    ar
    

    и

    Word Sort
    ---------
    a_e
    aa
    ac
    a-f
    ah
    aka
    a'kb
    akc
    am
    ar
    

    Хотя вы «потеряете» поведение «сортировки строк», я не уверен, что назвал бы это «функцией».Это поведение, которое было сочтено нежелательным (о чем свидетельствует тот факт, что оно не было перенесено ни в одно из сопоставлений Windows).Тем не менее, является определенной разницей в поведении между двумя параметрами сортировки (опять же, только для данных, не относящихся к EBCDIC VARCHAR), и у вас может быть код и / или ожидания клиентов, основанные на «сортировке строк»поведение. Это требует тестирования вашего кода и, возможно, исследования, чтобы выяснить, может ли это изменение поведения оказать какое-либо негативное влияние на пользователей.

  • Еще одно различие между SQL_Latin1_General_CP1_CI_AS и Latin1_General_100_CI_AS это возможность расширений на VARCHAR данных (NVARCHAR данные уже могут делать это для большинства SQL_ сопоставлений), например, обрабатывать æ, как если бы это было ae:

    IF ('æ' COLLATE SQL_Latin1_General_CP1_CI_AS =
        'ae' COLLATE SQL_Latin1_General_CP1_CI_AS)
    BEGIN
      PRINT 'SQL_Latin1_General_CP1_CI_AS';
    END;
    
    IF ('æ' COLLATE Latin1_General_100_CI_AS =
        'ae' COLLATE Latin1_General_100_CI_AS)
    BEGIN
      PRINT 'Latin1_General_100_CI_AS';
    END;
    

    Возвраты:

    Latin1_General_100_CI_AS
    

    Единственное, что вы «теряете» здесь - это не возможность выполнять эти расширения.Вообще говоря, это еще одно преимущество перехода на Windows Collation.Однако, как и при перемещении «Сортировка строк» ​​в «Сортировка слов», применяется то же предостережение: это определенная разница в поведении между двумя параметрами сортировки (опять же, только для данных VARCHAR), и у вас может быть код и/ или ожидания клиентов, основанные на , а не , имеющих эти сопоставления. Это требует тестирования вашего кода и, возможно, исследования, чтобы выяснить, может ли это изменение поведения оказать какое-либо негативное влияние на пользователей.

    (впервые отмечено в @ 1098 * ответе Зарепета и расширен здесь)

  • Еще одно отличие (которое также является преимуществом перехода на Windows Collation) заключается в том, что фильтрация столбца VARCHAR, который проиндексирован на NVARCHAR литерал / переменная / столбец, вы больше не будете делать недействительным индекс для столбца VARCHAR.Это связано с тем, что в Windows Collations используются одинаковые правила сортировки и сравнения Unicode для данных VARCHAR и NVARCHAR.Поскольку порядок сортировки между двумя типами одинаков, когда данные VARCHAR преобразуются в NVARCHAR (явным или неявным образом из-за приоритета типа данных), порядок элементов в индексе остается действительным.Подробнее об этом поведении см. В моем посте: Влияние на индексы при смешивании типов VARCHAR и NVARCHAR .

  • Сортировка на уровне сервера используется для установкиПодборка системных баз данных, в которую входит [model].База данных [model] используется в качестве шаблона для создания новых баз данных, включая [tempdb] при каждом запуске сервера.Таким образом, если сопоставление по умолчанию для базы данных не соответствует сопоставлению по умолчанию и экземпляра, то вы присоединяете локальные таблицы к временным таблицам в строковых полях, тогда вы получите ошибку несоответствия сопоставления.К счастью, существует несколько простой способ исправить различия в сопоставлении между «текущей» базой данных при выполнении CREATE #TempTable и [tempdb].При создании временных таблиц объявляйте параметры сортировки (для строковых столбцов) с помощью предложения COLLATE и используйте конкретное сопоставление (если вы знаете, что БД всегда будет использовать это сопоставление), или DATABASE_DEFAULT (если это не таквсегда знать параметры сортировки БД, в которой будет выполняться этот код):

    CREATE TABLE #Temp (Col1 NVARCHAR(40) COLLATE DATABASE_DEFAULT);
    

    Это необязательно для табличных переменных, поскольку они получают параметры сортировки по умолчанию из «текущей» базы данных.Однако, если у вас есть и табличные переменные, и временные таблицы, и вы присоединяете их к строковым полям, вам нужно будет использовать COLLATE {specific_collation} или COLLATE DATABASE_DEFAULT, как показано выше.

  • СерверУровень сортировки также управляет именами локальных переменных, CURSOR именами переменных и GOTO метками.Хотя ни одно из них не будет затронуто конкретным изменением, рассматриваемым в этом Вопросе, об этом, по крайней мере, следует знать.

  • Лучше всего использовать самую последнюю версию требуемой сортировки, если доступно несколько версий. Начиная с SQL Server 2005, была представлена ​​серия параметров сортировки «90», а в SQL Server 2008 была представлена ​​серия параметров сортировки «100». Вы можете найти эти сопоставления, используя следующие запросы:

    SELECT * FROM sys.fn_helpcollations() WHERE [name] LIKE N'%[_]90[_]%'; -- 476
    
    SELECT * FROM sys.fn_helpcollations() WHERE [name] LIKE N'%[_]100[_]%'; -- 2686
    
  • ТАКЖЕ, хотя вопрос задается о сопоставлениях без учета регистра, следует отметить, что если кто-то хочет внести аналогичные изменения, но использует сопоставления с учетом регистра, тогда еще одно отличие между сопоставлениями SQL Server и Windows Сортировки, для VARCHAR только для данных , в каком случае сортируются первыми. Это означает, что если у вас есть и A, и a, то параметры сортировки SQL_ будут сортировать A до a, тогда как параметры сортировки, отличные от SQL_ (и параметры сортировки SQL_ при работе с NVARCHAR данные) будет сортировать a до A.

Для получения дополнительной информации об изменении параметров сортировки базы данных или всего экземпляра см. Мой пост:
Изменение параметров сортировки экземпляра, баз данных и всех столбцов во всех пользовательских базах данных: что может быть неправильным?

Для получения дополнительной информации о работе со строками и сопоставлениями, пожалуйста, посетите: Информация сопоставления

14 голосов
/ 09 июня 2011

На этом форуме MSDN есть дополнительная информация:

http://social.msdn.microsoft.com/Forums/en-US/sqlgetstarted/thread/196b4586-1338-434d-ba8c-49fa3c9bdeeb/

Что гласит:

Вы должны увидеть небольшую разницу, если сортировка SQL_Latin1_General_CP1_CI_AS илиLatin1_General_CI_AS, но оба имеют случаи, когда они быстрее или медленнее, чем другие.

Latin1_General_CI_AS: - Latin1-General, регистр, нечувствителен, не зависит от акцента, канат, нечувствителен к ширине

SQL_Latin1_General_CP1_CI_AS: - Latin1-General, нечувствительный к регистру, нечувствительный к акценту, нечувствительный к канатипу, нечувствительный к ширине для данных Unicode, порядок сортировки SQL Server 52 на кодовой странице 1252 для данных, отличных от Unicode

Поэтомупо моему мнению, вы не должны видеть разницу, особенно если ваши данные только a-z0-9

5 голосов
/ 09 июня 2011
SELECT * FROM ::fn_helpcollations()
WHERE name IN (
'SQL_Latin1_General_CP1_CI_AS',
'Latin1_General_CI_AS'
)

... дает ...

Latin1_General_CI_AS: Latin1-General, нечувствительный к регистру, чувствительный к акценту, нечувствительный к типу, нечувствительный к ширине

SQL_Latin1_General_CP1_CI_AS: Latin1-Общее, без учета регистра, с учетом акцента, без учета канатического типа, с учетом ширины для данных Unicode, порядок сортировки SQL Server 52 на кодовой странице 1252 для данных не-Unicode

Итак, из этогоЯ бы сделал вывод, что используемая кодовая страница одинакова (Latin1-General => 1252), поэтому вы не должны не столкнуться с потерей данных - если что-то изменится после преобразования, это может быть порядок сортировки- что, вероятно, несущественно.

0 голосов
/ 25 октября 2018

Для этого перейдите в свойства вашей базы данных и выберите опции.

Затем измените тип коллекции на SQL_Latin1_General_CP1_CS_AS.

enter image description here

...