Accent Sensitive Sort

19

Почему эти два SELECTоператора приводят к другому порядку сортировки?

USE tempdb;
CREATE TABLE dbo.OddSort 
(
    id INT IDENTITY(1,1) PRIMARY KEY
    , col1 NVARCHAR(2)
    , col2 NVARCHAR(2)
);
GO
INSERT dbo.OddSort (col1, col2) 
VALUES (N'e', N'eA')
    , (N'é', N'éB')
    , (N'ë', N'ëC')
    , (N'è', N'èD')
    , (N'ê', N'êE')
    , (N'ē', N'ēF');
GO

SELECT * 
FROM dbo.OddSort 
ORDER BY col1 COLLATE Latin1_General_100_CS_AS;
╔════╦══════╦══════╗
║ id ║ col1 ║ col2 ║
╠════╬══════╬══════╣
║ 1 ║ e ║ eA ║
║ 2 é é ║ éB ║
║ 4 è è ║ èD ║ - должен быть id 3?
║ 5 ê ê ║ êE ║
║ 3 ë ë ║ ëC ║
║ 6 ║ ē ║ ēF ║
╚════╩══════╩══════╝
SELECT * 
FROM dbo.OddSort 
ORDER BY col2 COLLATE Latin1_General_100_CS_AS;
╔════╦══════╦══════╗
║ id ║ col1 ║ col2 ║
╠════╬══════╬══════╣
║ 1 ║ e ║ eA ║
║ 2 é é ║ éB ║
║ 3 ë ë ║ ëC ║
║ 4 è è ║ èD ║
║ 5 ê ê ║ êE ║
║ 6 ║ ē ║ ēF ║
╚════╩══════╩══════╝
Арам
источник

Ответы:

13

Этот вопрос связан не столько с базами данных, сколько с обработкой и правилами Unicode.

На основе https://docs.microsoft.com/en-us/sql/t-sql/statements/windows-collation-name-transact-sql Latin1_General_100_CS_AS означает: «Сортировка использует общие правила сортировки словаря Latin1 и сопоставляется с кодовой страницей 1252 "с добавленным CS = чувствительным к регистру и AS = чувствительным к акценту.

Сопоставление между кодовой страницей Windows 1252 и Unicode ( http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT ) показывает одинаковые значения для всех символов, с которыми мы имеем дело (кроме e с макроном) этого не существует в картографировании Microsoft, так что понятия не имеем, что он делает с этим делом), поэтому мы можем пока сосредоточиться на инструментах и ​​терминологии Unicode.

Во-первых, дайте нам знать точно, с чем мы имеем дело, для всех ваших строк:

0065  LATIN SMALL LETTER E
0041  LATIN CAPITAL LETTER A
00E9  LATIN SMALL LETTER E WITH ACUTE
0042  LATIN CAPITAL LETTER B
00EB  LATIN SMALL LETTER E WITH DIAERESIS
0043  LATIN CAPITAL LETTER C
00E8  LATIN SMALL LETTER E WITH GRAVE
0044  LATIN CAPITAL LETTER D
00EA  LATIN SMALL LETTER E WITH CIRCUMFLEX
0045  LATIN CAPITAL LETTER E
0113  LATIN SMALL LETTER E WITH MACRON
0046  LATIN CAPITAL LETTER F

Алгоритм сопоставления Unicode описан здесь: https://www.unicode.org/reports/tr10/

Взгляните на раздел 1.3 «Чувствительность к контексту», в котором объясняется, что сортировка не может зависеть только от одного символа за другим, так как некоторые правила зависят от контекста.

Обратите внимание также на эти пункты в 1.8:

Сортировка не является свойством строк. Порядок сортировки, как правило, не сохраняется при операциях конкатенации или подстроки.

По умолчанию алгоритм использует три полностью настраиваемых уровня. Для латинского алфавита эти уровни примерно соответствуют:

alphabetic ordering
diacritic ordering
case ordering.

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

Вы можете ознакомиться с конкретными правилами сортировки по латыни здесь: http://developer.mimer.com/collations/charts/latin.htm или, более конкретно, специально для MS SQL: http://collation-charts.org/mssql/mssql. 0409.1252.Latin1_General_CS_AS.html

Для eперсонажа это показывает:

e E é É è È ê Ê ë Ë

Это объясняет ваши результаты при оформлении заказа, col1за исключением того, что ē не существует в кодовой странице 1252, поэтому я абсолютно не представляю, что с ним делать.

Или, если мы делаем алгоритм Unicode вручную, используя значение ключей DUCET по адресу http://www.unicode.org/Public/UCA/latest/allkeys.txt :

шаг 1: нормализация формы D, поэтому каждый случай становится:

e => U+0065
é => U+0065 U+0301
ë => U+0065 U+0308
è => U+0065 U+0300
ê => U+0065 U+0302
ē => U+0065 U+0304

Шаг 2. Создание массивов сопоставления (поиск в файле allkeys.txt)

e => [.1D10.0020.0002]
é => [.1D10.0020.0002] [.0000.0024.0002]
ë => [.1D10.0020.0002] [.0000.002B.0002]
è => [.1D10.0020.0002] [.0000.0025.0002]
ê => [.1D10.0020.0002] [.0000.0027.0002]
ē => [.1D10.0020.0002] [.0000.0032.0002]

шаг 3, сформируйте ключи сортировки (для каждого уровня возьмите каждое значение в каждом массиве сопоставления, затем поместите 0000 в качестве разделителя и начните снова для следующего уровня)

e => 1D10 0000 0020 0000 0002
é => 1D10 0000 0020 0024 0000 0002 0002
ë => 1D10 0000 0020 002B 0000 0002 0002
è => 1D10 0000 0020 0025 0000 0002 0002
ê => 1D10 0000 0020 0027 0000 0002 0002
ē => 1D10 0000 0020 0032 0000 0002 0002

Шаг 4. Сравнение ключей сортировки (простое двоичное сравнение каждого значения по одному): четвертого значения достаточно, чтобы отсортировать их все, поэтому конечный порядок становится следующим:

e
é
è
ê
ë
ē

Таким же образом для заказа на col2:

Шаг 1: НФД

eA => U+0065 U+0041
éB => U+0065 U+0301 U+0042
ëC => U+0065 U+0308 U+0043
èD => U+0065 U+0300 U+0044
êE => U+0065 U+0302 U+0045
ēF => U+0065 U+0304 U+0046

шаг 2: сопоставления массивов

eA => [.1D10.0020.0002] [.1CAD.0020.0008]
éB => [.1D10.0020.0002] [.0000.0024.0002] [.1CC6.0020.0008]
ëC => [.1D10.0020.0002] [.0000.002B.0002] [.1CE0.0020.0008]
èD => [.1D10.0020.0002] [.0000.0025.0002] [.1CF5.0020.0008]
êE => [.1D10.0020.0002] [.0000.0027.0002] [.1D10.0020.0008]
ēF => [.1D10.0020.0002] [.0000.0032.0002] [.1D4B.0020.0008]

шаг 3: сформировать ключи сортировки

eA => 1D10 1CAD 0000 0020 0020 0000 0002 0008
éB => 1D10 1CC6 0000 0020 0024 0020 0000 0002 0002 0008
ëC => 1D10 1CE0 0000 0020 002B 0020 0000 0002 0002 0008
èD => 1D10 1CF5 0000 0020 0025 0020 0000 0002 0002 0008
êE => 1D10 1D10 0000 0020 0027 0020 0000 0002 0002 0008
ēF => 1D10 1D4B 0000 0020 0032 0020 0000 0002 0002 0008

Шаг 4: Сравните ключи сортировки: второго значения достаточно, чтобы отсортировать их все, и оно фактически уже в возрастающем порядке, поэтому окончательный порядок действительно:

eA
éB
ëC
èD
êE
ēF

Обновление : добавление третьего случая Соломона Руцкого, который более хитрый из-за пробела, который позволяет вводить новые правила (я выбрал «случай невежественного»):

Шаг 1, NFD:

è 1 => U+0065 U+0300 U+0020 U+0031
ê 5 => U+0065 U+0302 U+0020 U+0035
e 2 => U+0065 U+0020 U+0032
é 4 => U+0065 U+0301 U+0020 U+0034
ē 3 => U+0065 U+0304 U+0020 U+0033
ë 6 => U+0065 U+0308 U+0020 U+0036

Шаг 2, Создание массивов сопоставления:

è 1 => [.1D10.0020.0002] [.0000.0025.0002] [*0209.0020.0002] [.1CA4.0020.0002]
ê 5 => [.1D10.0020.0002] [.0000.0027.0002] [*0209.0020.0002] [.1CA8.0020.0002]
e 2 => [.1D10.0020.0002] [*0209.0020.0002] [.1CA5.0020.0002]
é 4 => [.1D10.0020.0002] [.0000.0024.0002] [*0209.0020.0002] [.1CA7.0020.0002]
ē 3 => [.1D10.0020.0002] [.0000.0032.0002] [*0209.0020.0002] [.1CA6.0020.0002]
ë 6 => [.1D10.0020.0002] [.0000.002B.0002] [*0209.0020.0002] [.1CA9.0020.0002]

Шаг 3, Форма сортировки ключей:

è 1 => 1D10 0209 1CA4 0000 0020 0025 0020 0020 0000 0002 0002 0002 0002
ê 5 => 1D10 0209 1CA8 0000 0020 0027 0020 0020 0000 0002 0002 0002 0002
e 2 => 1D10 0209 1CA5 0000 0020 0020 0020 0000 0002 0002 0002
é 4 => 1D10 0209 1CA7 0000 0020 0024 0020 0020 0000 0002 0002 0002 0002
ē 3 => 1D10 0209 1CA6 0000 0020 0032 0020 0020 0000 0002 0002 0002 0002
ë 6 => 1D10 0209 1CA9 0000 0020 002B 0020 0020 0000 0002 0002 0002 0002

шаг 4, сравнить ключи сортировки:

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

è 1
e 2
ē 3
é 4
ê 5
ë 6

Второе обновление на основе комментария Соломона Руцкого о версиях Unicode.

В то время я использовал allkeys.txtданные о последней версии Unicode, то есть версии 10.0.

Если вместо этого нам нужно учесть Unicode 5.1 , это будет: http://www.unicode.org/Public/UCA/5.1.0/allkeys.txt

Я только что проверил, для всех символов, приведенных выше, вместо этого используются следующие параметры сортировки:

e => [.119D.0020.0002.0065]
é => [.119D.0020.0002.0065] [.0000.0032.0002.0301]
ë => [.119D.0020.0002.0065] [.0000.0047.0002.0308]
è => [.119D.0020.0002.0065] [.0000.0035.0002.0300]
ê => [.119D.0020.0002.0065] [.0000.003C.0002.0302]
ē => [.119D.0020.0002.0065] [.0000.005B.0002.0304]

и:

eA => [.119D.0020.0002.0065] [.1141.0020.0008.0041]
éB => [.119D.0020.0002.0065] [.0000.0032.0002.0301] [.1157.0020.0008.0042]
ëC => [.119D.0020.0002.0065] [.0000.0047.0002.0308] [.116F.0020.0008.0043]
èD => [.119D.0020.0002.0065] [.0000.0035.0002.0300] [.1182.0020.0008.0044]
êE => [.119D.0020.0002.0065] [.0000.003C.0002.0302] [.119D.0020.0008.0045]
ēF => [.119D.0020.0002.0065] [.0000.005B.0002.0304] [.11D5.0020.0008.0046]

и:

è 1 => [.119D.0020.0002.0065] [.0000.0035.0002.0300] [*0209.0020.0002.0020] [.1138.0020.0002.0031]
ê 5 => [.119D.0020.0002.0065] [.0000.003C.0002.0302] [*0209.0020.0002.0020] [.113C.0020.0002.0035]
e 2 => [.119D.0020.0002.0065] [*0209.0020.0002.0020] [.1139.0020.0002.0032]
é 4 => [.119D.0020.0002.0065] [.0000.0032.0002.0301] [*0209.0020.0002.0020] [.113B.0020.0002.0034]
ē 3 => [.119D.0020.0002.0065] [.0000.005B.0002.0304] [*0209.0020.0002.0020] [.113A.0020.0002.0033]
ë 6 => [.119D.0020.0002.0065] [.0000.0047.0002.0308] [*0209.0020.0002.0020] [.113D.0020.0002.0036]

которые затем вычисляют следующие ключи сортировки:

e => 119D 0000 0020 0000 0002 0000 0065
é => 119D 0000 0020 0032 0000 0002 0002 0000 0065 0301
ë => 119D 0000 0020 0047 0000 0002 0002 0000 0065 0308
è => 119D 0000 0020 0035 0000 0002 0002 0000 0065 0300
ê => 119D 0000 0020 003C 0000 0002 0002 0000 0065 0302
ē => 119D 0000 0020 005B 0000 0002 0002 0000 0065 0304

и:

eA => 119D 1141 0000 0020 0020 0000 0002 0008 0000 0065 0041
éB => 119D 1157 0000 0020 0032 0020 0000 0002 0002 0008 0000 0065 0301 0042
ëC => 119D 116F 0000 0020 0047 0020 0000 0002 0002 0008 0000 0065 0308 0043
èD => 119D 1182 0000 0020 0035 0020 0000 0002 0002 0008 0000 0065 0300 0044
êE => 119D 119D 0000 0020 003C 0020 0000 0002 0002 0008 0000 0065 0302 0045
ēF => 119D 11D5 0000 0020 005B 0020 0000 0002 0002 0008 0000 0065 0304 0046

и:

è 1 => 119D 0209 1138 0000 0020 0035 0020 0020 0000 0002 0002 0002 0002 0000 0065 0300 0020 0031
ê 5 => 119D 0209 113C 0000 0020 003C 0020 0020 0000 0002 0002 0002 0002 0000 0065 0302 0020 0035
e 2 => 119D 0209 1139 0000 0020 0020 0020 0000 0002 0002 0002 0000 0065 0020 0032
é 4 => 119D 0209 113B 0000 0020 0032 0020 0020 0000 0002 0002 0002 0002 0000 0065 0301 0020 0034
ē 3 => 119D 0209 113A 0000 0020 005B 0020 0020 0000 0002 0002 0002 0002 0000 0065 0304 0020 0033
ë 6 => 119D 0209 113D 0000 0020 0047 0020 0020 0000 0002 0002 0002 0002 0000 0065 0308 0020 0036

что снова дает эти три отсортированных результата:

e
é
è
ê
ë
ē

и

eA
éB
ëC
èD
êE
ēF

и

è 1
e 2
ē 3
é 4
ê 5
ë 6
Патрик Мевзек
источник
Привет, Патрик. Спасибо за размещение этой подробной информации. Несколько замечаний: 1) Вы можете игнорировать кодовую страницу 1252. Это относится к VARCHAR(то есть не-Unicode) данным, которые здесь не используются. Вот почему ēперсонаж работает просто отлично. 2) Информация о "таблицах сортировки" немного устарела. Это для предыдущей версии этого сопоставления, и они ничего не публиковали с 2009 года. 3) Версия Unicode здесь определенно не самая последняя (версия 10). _100_Серия Параметры сортировки пришел с SQL 2008, так что это будет Unicode 5,0 или 5,1: unicode.org/standard/versions/#TUS_Earlier_Versions
Соломон Rutzky
Я не думаю, что allKeys.txt изменения между версией Unicode, кроме добавления новых символов, так что вышеупомянутое должно остаться верным, но, конечно, это может быть переделано с предыдущими старыми данными, мне просто не хватает энергии, чтобы снова потратить на это несколько часов. Что касается CP1252, то он просто исходил из определения, данного MS-SQL (я сам не использую этот продукт).
Патрик Мевзек,
1) Вероятно, между версиями нет серьезных изменений, но я уверен, что, по крайней мере, есть поправки веса / классификации. Но да, я определенно получаю временные ограничения;) 2) Что касается CP1252, я упоминал об этом, потому что концепция кодовых страниц не существует в Юникоде. Юникод - это средство, которое никогда не требует кодовых страниц. В документе MS по общему признанию неясно, но в самом начале упоминается « Кодовая страница, используемая для хранения данных символов, отличных от Unicode ». Вы правы, что один символ отсутствует в CP1252, но кодовые страницы здесь не используются.
Соломон Руцкий
Да, я никогда не говорил ничего о кодовой странице, связанной с Unicode. Это просто документация по MS SQL, в которой говорится, что это имя сопоставления работает с «кодовой страницей 1252». Это, вероятно, не имеет смысла (это не для меня, но опять же, не для пользователя), но это то, что написано в документации этого программного обеспечения. Что касается повторного выполнения задания, не стесняйтесь сделать это или просто внесите изменения в сортировку, относящиеся к персонажам в игре, здесь между Unicode 5 и новее, если таковые имеются и если вы хотите. Я считаю, что мой ответ остается верным, точным и строит результаты на основе входных данных, а не наоборот.
Патрик Мевзек
3) re: предложение № 1: хотя в основном это касается Unicode, этот вопрос является проблемой ОС, так как MS реализовала спецификацию и, возможно, не сделала все это и / или могла допустить некоторые ошибки. Я обнаружил 2 ошибки в .NET относительно того, как он определяет «категорию» или «блок», в котором находится конкретный символ (они неправильно идентифицировали небольшой сегмент символов). Кроме того , это является , по крайней мере немного, проблема SQL Server, только потому , что SQL Server эффективно снимок каждого разбор по копиям в момент времени (для согласованности между версиями), чтобы они могли иметь то , что теперь SQL Server конкретного поведения.
Соломон Руцкий
16

Поведение, которое вы здесь видите, связано в общем смысле с тем фактом, что алгоритм сопоставления Unicode (UCA) допускает сложную многоуровневую сортировку. Более конкретно:

  1. Сортировка не Сравнение:

    Определить, являются ли две строки одинаковыми или разными, довольно просто (учитывая конкретную локаль / язык и набор чувствительности). Но определение порядка 2 или более строк может быть очень сложным.

  2. Сортировка выполняется в несколько этапов, причем каждый шаг применяется ко всей строке, а не по символам:

    1. Стандартный: сортировка базовых символов (независимо от ударения и разницы в регистре)
    2. ЕСЛИ чувствительный к акценту, применять акцент / диакритические веса
    3. ЕСЛИ чувствителен к регистру, применять веса корпуса

Когда вы сортируете по col1(одиночному символу), он сначала определяет, что все символы имеют одинаковый вес, так как все они - « е ». Затем, это применяет акцент / диакритические веса. Различий в корпусах нет, поэтому третий шаг ничего не изменит. Таким образом, единственные различия заключаются в шаге 2, поэтому для этих строк существует предпочтительный порядок col1.

При сортировке по col2(двум символам) сначала определяется, что каждая строка имеет разный вес, поскольку оба символа используются для определения веса сортировки (например, « ea », « eb » и т. Д.). Затем, это применяет акцент / диакритические веса. Различий в корпусах нет, поэтому третий шаг ничего не изменит. Так что на этот раз есть различия в шагах 1 и 2. Но поскольку различия в шаге 1 уже были применены к каждой строке до того, как учитываются весовые коэффициенты на шаге 2, весовые коэффициенты на шаге 2 не влияют на порядок; они будут применяться только если веса из шага 1 для двух или более строк были одинаковыми.

Следующая адаптация примера кода из вопроса, мы надеемся, иллюстрирует поведение сортировки, описанное выше. Я добавил несколько дополнительных строк и дополнительный столбец, чтобы показать влияние чувствительности сортировки на регистр (поскольку исходные данные образца строчные):

НАСТРОИТЬ

USE [tempdb];

-- DROP TABLE dbo.OddSort;
CREATE TABLE dbo.OddSort
(
    id INT IDENTITY(1,1) PRIMARY KEY,
    col1 NVARCHAR(5) COLLATE Latin1_General_100_CS_AS,
    col2 NVARCHAR(5) COLLATE Latin1_General_100_CS_AS,
    col3 NVARCHAR(5) COLLATE Latin1_General_100_CS_AS
);
GO

INSERT dbo.OddSort (col1, col2, col3)
VALUES (N'e', N'eA', N'e A')
     , (N'ê', N'êE', N'ê E')
     , (N'é', N'éH', N'é H')
     , (N'ë', N'ëC', N'ë C')
     , (N'E', N'EG', N'E G')
     , (N'Ë', N'ëh', N'ë h')
     , (N'è', N'èD', N'è D')
     , (N'é', N'éB', N'é B')
     , (N'ë', N'ëH', N'ë H')
     , (N'ē', N'ēF', N'ē F');

ТЕСТ 1

SELECT [id], [col1], UNICODE([col1]) AS [CodePoint]
FROM dbo.OddSort 
ORDER BY col1;

Возвращает:

id    col1    CodePoint
1     e       101
5     E       69
8     é       233
3     é       233
7     è       232
2     ê       234
4     ë       235
9     ë       235
6     Ë       203
10    ē       275

Что мы можем видеть в результатах выше:

  1. Кодовая точка не определяет порядок сортировки
  2. Неакцентированные символы сортируются перед акцентированными символами (внутри той же буквы: f все равно будет идти после всех этих). Понятно, что акцентные веса применяются перед весовыми коэффициентами.
  3. Строчные сорта до верхнего регистра в том же ударением (или не-ударением) характер (то есть е , то Е , и ледиМел затем Ë ). Эта адаптация используется большинством параметров сортировки Windows, в то время как большинство параметров сортировки SQL Server сначала сортируются в верхнем регистре.

ТЕСТ 2

SELECT [id], [col2]
FROM dbo.OddSort 
ORDER BY col2;

Возвращает:

id    col2
1     eA
8     éB
4     ëC
7     èD
2     êE
10    ēF
5     EG
3     éH
6     ëh
9     ëH

Что мы можем видеть в результатах выше:

  1. Сортировка первого уровня действительно является базовыми символами. Если бы это были акценты / диакритические знаки, то строки С (id = 4), ēF (id = 10) и EG (id = 5) не были бы там, где они есть. Если бы это был корпус, то строка EG (id = 5) не была бы там, где она есть.
  2. Сортировка второго уровня действительно является акцентами / диакритическими знаками. Это объясняет, почему последние три строки обозначают éH -> ëh -> ÀH вместо ëh -> éH -> ëH (т. Е. Идентификаторы 3 -> 6 -> 9 вместо 6 -> 3 -> 9).
  3. Сортировка третьего уровня действительно является оболочкой. Вот почему последние 2 строки являются « h ->» H , поскольку строчные буквы сортируются первыми.

ТЕСТ 3

SELECT [id], [col3]
FROM dbo.OddSort 
ORDER BY col3;

Возвращает:

id    col3
1     e A
8     é B
4     ë C
7     è D
2     ê E
10    ē F
5     E G
3     é H
6     ë h
9     ë H

Что мы можем видеть в результатах выше:

  1. Порядок сортировки точно такой же, как в Тесте 2. Единственная разница в значениях теста здесь заключается в том, что между каждым символом есть пробел, что исключает возможность контекстных правил. Следовательно, мы знаем, что причина различий в порядке сортировки col2в вопросе опять-таки связана с «многоуровневым сравнением», а не с «контекстной чувствительностью».

Дополнительные замечания:

  1. Что касается получения точных правил, это не так просто, как должно быть. Проблема с получением конкретных объяснений этих правил заключается в том, что правила сортировки Unicode, хотя и задокументированы, являются рекомендацией. Поставщики, такие как Microsoft, должны выполнять эти рекомендации. Microsoft не выполнила рекомендации в точности так, как указано в документации по Unicode, поэтому существует разрыв (аналогично тому, как спецификации HTML или CSS не реализованы ни полностью, ни даже одинаково для разных поставщиков). Затем существуют разные версии Windows Collations (вы используете версию, 100которая вышла с SQL Server 2008), и она связана с версией Unicode, которая намного старше текущей версии Unicode или демонстрационной версии ICU Collation.использует. Например, раздел « Что нового в SQL Server 2008 Collations » документации «Поддержка сортировки и Unicode» для SQL Server 2008 содержит два очень интересных момента о том, что является «новым» в _100_серии Collations:

    1. Таблица вариантов Unicode 5.0.

      Unicode 5.0 был опубликован в июле 2006 года (ну, тогда была выпущена база данных персонажей, а полная спецификация последовала в конце 2006 года). Текущая версия 10.0, которая была опубликована в июне 2017 года. И учитывая модель выпуска за последние 4 года, вполне вероятно, что версия 11.0 выйдет где-то в середине 2018 года.

    2. Взвешивание было добавлено к ранее не взвешенным символам, которые сравнивались бы одинаково.

      Эти весовые коэффициенты были более чем вероятно определены в стандарте Unicode, но не в этой реализации.

     
    Тем не менее, приведенная выше документация по УЦА является хорошим началом.

  2. Ключи сортировки, используемые Windows / .NET / SQL Server, не совсем такие, как показано в стандарте Unicode (см. Ответ @ Patrick) или реализованы в ICU . Чтобы увидеть, что использует Windows / .NET / SQL Server, вы можете попробовать метод CompareInfo.GetSortKey . Я создал UDF SQLCLR для передачи этих значений и получения ключа сортировки. Обратите внимание, что я использую SQL Server 2017 в Windows 10 с установленным .NET Framework 4.5 - 4.6.1, поэтому .NET должен использовать Unicode 6.0.0. Кроме того, Level4 не используется для этих строк.

    CHAR    L1     L2     L3     L4
    e      0E21
    E      0E21           12
    ë      0E21    13
    Ë      0E21    13     12

    Рассмотрение этих ключей сортировки для теста 1 и понимание того, что уровни сортируются как несколько столбцов в ORDER BYпредложении (L3 сортируется по одинаковым значениям L2, который сортируется по одинаковым значениям L1), должно проиллюстрировать, что причина поведения В этом вопросе отмечена возможность многоуровневой сортировки Unicode. Точно так же:

    CHAR       L1         L2       L3       L4
    EG      0E210E25              1212
    éH      0E210E2C      0E      0212
    ëh      0E210E2C      13
    ëH      0E210E2C      13      0212

    Рассматривая некоторые из ключей сортировки для Теста 2, мы видим, что сначала сортируются базовые символы (L1), затем сортируются акценты (L2), а затем сортируется регистр (L3).

  3. Поскольку тип данных есть NVARCHAR, нас интересуют только кодовые точки Unicode и алгоритмы сортировки, следовательно, использование UNICODE()функции в TEST 1. Хотя кодовые страницы указываются большинством параметров сортировки, они относятся только к VARCHARданным. Это означает, что в то время как кодовая страница 1252 определена Latin1_General*серией сопоставлений, здесь ее можно игнорировать.

  4. Веса, описанные в Таблице элементов сопоставления Unicode по умолчанию (DUCET) ( версия 5.0.0, которая должна сопоставляться с сопоставлениями _100_серии), подходят для английского языка США, но не для других языков / языков. Другие языки должны начинаться с DUCET, а затем применять правила переопределения для конкретной локали, как это определено проектом Common Locale Data Repository (CLDR). Насколько я могу судить, версии 1.4 / 1.4.1 были выпущены в 2006 году. Чтобы получить эти переопределения, загрузите файл «core» CLDR 1.4 через http://unicode.org/Public/cldr/1.4.0/core.zip. затем в этом zip-файле перейдите в папку параметров сортировки и найдите файл XML, соответствующий используемой локали. Эти файлы содержат только переопределения и не являются полным набором правил сопоставления.

Соломон Руцкий
источник