Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Pautov_MySQL_rukovodstvo_professionala.328368.rtf
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
713.1 Кб
Скачать

10.11.15: Почему cjk‑строки не сортируются правильно в Unicode? (I)

Иногда люди наблюдают, что результат поиска utf8_unicode_ci или ucs2_unicode_ci, либо сортировка ORDER BY не то, что они ожидали. Хотя мы никогда не исключаем возможность, что имеется ошибка, в прошлом было установлено, что много людей не читают правильно стандартную таблицу весов для алгоритма объединения Unicode. MySQL использует таблицу, найденную на http://www.unicode.org/Public/UCA/4.0.0/allkeys‑4.0.0.txt79. Это не первая таблица, которую Вы найдете, начав с unicode.org, потому что MySQL использует старую таблицу 4.0.0 allkeys , а не более новую 4.1.0. Это потому, что разработчики очень осторожны относительно изменения упорядочения, которое воздействует на индексы, чтобы не вызывать ситуации типа сообщенной в Глюке #1652680, иллюстрируемой следующим образом:

mysql< CREATE TABLE tj (s1 CHAR(1) CHARACTER SET utf8 COLLATE

utf8_unicode_ci);

Query OK, 0 rows affected (0.05 sec)

mysql> INSERT INTO tj VALUES ('уБМ'),('уБЛ');

Query OK, 2 rows affected (0.00 sec)

Records: 2 Duplicates: 0 Warnings: 0

mysql> SELECT * FROM tj WHERE s1 = 'уБЛ';

+‑‑‑‑‑+

| s1 |

+‑‑‑‑‑+

| уБМ |

| уБЛ |

+‑‑‑‑‑+

2 rows in set (0.00 sec)

Символ в первой строке результатов не тот, который мы искали. Почему MySQL находит это? Сначала мы ищем значение отметки кода Unicode, которое является возможным, читая шестнадцатеричный номер для ucs2‑версии символов:

mysql> SELECT s1, HEX(CONVERT(s1 USING ucs2)) FROM tj;

+‑‑‑‑‑+‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑+

| s1 | HEX(CONVERT(s1 USING ucs2)) |

+‑‑‑‑‑+‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑+

| уБМ | 304C |

| уБЛ | 304B |

+‑‑‑‑‑+‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑+

2 rows in set (0.03 sec)

Теперь мы ищем 304B и 304C в таблице 4.0.0 allkeys и находим эти строки:

304B; [.1E57.0020.000E.304B] # HIRAGANA LETTER KA

304C; [.1E57.0020.000E.304B][.0000.0140.0002.3099] # HIRAGANA LETTER GA; QQCM

Официальные имена Unicode (после метки #) сообщают нам японский символ (Hiragana), неофициальную классификацию (символ, цифра или знак препинания) и западный идентификатор (KA или GA, произносимые и непроизносимые компоненты той же самой пары символов). Более важен первичный вес (primary weight , первый шестнадцатеричный номер внутри квадратных скобок) 1E57 на обеих строках. Для сравнений в поиске и сортировке MySQL использует только первичный вес, игнорируя все другие числа. Это означает, что мы сортируем уБМ и уБЛ правильно, согласно Unicode спецификации. Если мы хотим отличить их, мы должны будем использовать non‑UCA (Unicode Collation Algorithm) объединение (utf8_unicode_bin или utf8_general_ci), либо сравнивать значения HEX(), либо применять ORDER BY CONVERT(s1 USING sjis). Быть правильным, согласно Unicode, конечно, недостаточно: человек, который представил на рассмотрение ошибку, был прав. Мы планируем добавлять другое объединение для японских символов согласно стандарту JIS X 4061, в котором высказанные/невысказанные пары символов, подобные KA/GA, являются различимыми для целей упорядочения.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]