+------+--------+------+-------+---------+-----+------+------+------+------+
| 30DA | E3839A | C772 | 8379 | A5DA |ABDA |A5DA | A5DA | 8379 | A5DA |
+------+--------+------+-------+---------+-----+------+------+------+------+
1 row in set (0.04 sec)
Так как ни одно из значений столбца не 3F, то есть символ вопросительного знака (?), мы знаем, что каждое преобразование сработало.
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.txt. Это не первая таблица, которую Вы найдете, начав с unicode.org, потому что MySQL использует старую таблицу 4.0.0 allkeys , а не более новую 4.1.0. Это потому, что разработчики очень осторожны относительно изменения упорядочения, которое воздействует на индексы, чтобы не вызывать ситуации типа сообщенной в Глюке #16526, иллюстрируемой следующим образом:
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, являются различимыми для целей упорядочения.
10.11.16: Почему CJK-строки не сортируются правильно в Unicode? (дополнение)
Если Вы используете Unicode (ucs2 или utf8) и Вы знаете порядок сортировки Unicode, но MySQL все еще сортирует Вашу таблицу неправильно, то Вы должны сначала проверить набор символов таблицы:
mysql> SHOW CREATE TABLE tG
******************** 1. row ******************
Table: t
Create Table: CREATE TABLE `t` (`s1` char(1) CHARACTER SET ucs2 DEFAULT NULL)
ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
Так как набор символов правильный, давайте посмотрим то, какую информацию таблица INFORMATION_SCHEMA.COLUMNS может обеспечивать относительно этого столбца:
mysql> SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME
– > FROM INFORMATION_SCHEMA.COLUMNS
– > WHERE COLUMN_NAME = 's1' AND TABLE_NAME = 't';
+-------------+--------------------+-----------------+
| COLUMN_NAME | CHARACTER_SET_NAME | COLLATION_NAME |
+-------------+--------------------+-----------------+
| s1 | ucs2 | ucs2_general_ci |
+-------------+--------------------+-----------------+
1 row in set (0.01 sec)
Вы можете видеть, что объединение ucs2_general_ci вместо ucs2_unicode_ci. Причина того, почему это так, может быть найдена, используя SHOW CHARSET, как показано здесь:
mysql> SHOW CHARSET LIKE 'ucs2%';