|
||||
|
10.11. MySQL 5 FAQ: поддержка наборов символов CJK Этот набор вопросов происходит из опыта поддержки MySQL в обработке запросов относительно проблем кириллицы и CJK (Chinese-Japanese-Korean). 10.11.1: Я вставил символы CJK в мою таблицу. Почему SELECT отображает их как символы ?? Эта проблема обычно из-за установки в MySQL, который не соответствует параметрам настройки для прикладной программы или операционной системы. Имеются некоторые общие шаги для исправления этих типов проблем: Определите версию MySQL . Используйте инструкцию SELECT VERSION(); для этого. Проверьте, что база данных фактически использует желательный набор символов.. Люди часто думают, что набор символов пользователя всегда такой же, как набор символов сервера используемый для целей отображения. Однако, оба эти предположения неправильны. Вы можете удостовериться в этом, проверяя результат SHOW CREATE TABLE tablename, а лучше используя эту инструкцию: SELECT character_set_name, collation_name FROM information_schema.columns WHERE table_schema = your_database_name AND table_name = your_table_name AND column_name = your_column_name; Определите шестнадцатеричное значение символа или символов, которые не отображаются правильно.. Вы можете получать эту информацию для столбца column_name в таблице table_name, используя следующий запрос: SELECT HEX(column_name) FROM table_name; 3F кодирует символ ?. Это означает, что ? является символом, фактически сохраненным в столбце. Это наиболее часто случается из-за проблемы при преобразовании специфического символа от Вашего набора символов пользователя до целевого набора символов. Удостоверьтесь, что возможное путешествие туда и обратно, то есть когда Вы выбираете literal (или _introducer hexadecimal-value), Вы получаете в результате именно literal. Например, японский символ Katakana Pe (уГЪ') существует во всех CJK наборах символов, и имеет значение 0x30da. Чтобы проверять путешествие туда и обратно для этого символа, используйте этот запрос: SELECT 'уГЪ' AS `уГЪ`; /* or SELECT _ucs2 0x30da; */ Если результат не такой, путешествие туда и обратно потерпело неудачу. Удостоверьтесь, что проблема не с окном просмотра или другой прикладной программой, а именно с MySQL. Используйте программу пользователя mysql (в Windows: mysql.exe), чтобы выполнить эту задачу. Если mysql отображает все правильно, но Ваша прикладная программа этого не делает, то проблема, вероятно, из-за параметров настройки системы. Чтобы выяснять, каковы Ваши параметры настройки, используйте инструкцию SHOW VARIABLES вывод которой должен походить на то, что показывается здесь: mysql> SHOW VARIABLES LIKE 'char%'; +--------------------------+----------------------------------------+ | Variable_name | Value | +--------------------------+----------------------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/local/mysql/share/mysql/charsets/ | +--------------------------+----------------------------------------+ 8 rows in set (0.03 sec) Это типичные параметры настройки набора символов для международно-ориентируемого пользователя (обратите внимание на использование utf8 Unicode), связанного с сервером на западе (latin1 является набором символов западной Европы и значением по умолчанию для MySQL). Хотя Unicode (обычно вариант utf8 на Unix и ucs2 в Windows) предпочтителен для Latin, это часто не то, что Ваши утилиты операционной системы поддерживают лучше всего. Много пользователей Windows находят, что набор символов Microsoft, типа cp932 для Japanese Windows, подходит им лучше. Если Вы не можете управлять параметрами настройки сервера, и Вы понятия не имеете, каков Ваш основной компьютер, то пробуйте изменить набор символов на общий для страны, в которой Вы находитесь (euckr = Korea; gb2312 или gbk = People's Republic of China; big5 = Taiwan; sjis, ujis, cp932 или eucjpms = Japan; ucs2 or utf8 = где угодно). Обычно необходимо изменить только параметры настройки пользователя, результатов и подключение. Имеется простая инструкция, которая изменяется все три сразу: SET NAMES. Например: SET NAMES 'big5'; Если только установка правильна, Вы можете делать это постоянным, редактируя my.cnf или my.ini. Например Вы могли бы добавлять строки, походящие на эти: [mysqld] character-set-server=big5 [client] default-character-set=big5 Также возможно, что имеются проблемы с установкой конфигурации API, используемой в вашей прикладной программе. 10.11.2: Какие китайские (GB) наборы символов понимает MySQL? MySQL поддерживает два общих варианта GB GB ( Guojia Biaozhun или национального эталона) набора символов, которые являются официальными в КНР: gb2312 и gbk. Иногда люди пробуют вставлять символы gbk в gb2312, и это работает в большинстве случаев, потому что gbk является надмножеством gb2312, но в конечном счете они пробуют вставлять старые китайские символы, и это не работает (см. Глюк #16072). Здесь мы пробуем разъяснять точно, какие символы являются законными в gb2312 или gbk в отношении официальных документов. Пожалуйста, проверьте эти ссылки перед сообщением об ошибках в gb2312 или gbk. Для полной распечатки символов gb2312, упорядоченных согласно объединению gb2312_chinese_ci: http://d.udm.net/bar/~bar/charts/gb2312_chinese_ci.html. MySQL gbk в действительности Microsoft code page 936. Это отличается от официального gbk для символов A1A4 (middle dot), A1AA (em dash), A6E0-A6F5 и A8BB-A8C0. Для получения распечатки различий см. http://recode.progiciels-bpi.ca/showfile.html?name=dist/libiconv/gbk.h. Для получения распечатки отображений gbk/Unicode см. http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT . Для получения распечатки MySQL-символов gbk см. http://d.udm.net/bar/~bar/charts/gbk_chinese_ci.html. 10.11.3: Какие проблемы я должен знать при работе с китайским набором символов Big5? MySQL поддерживает набор символов Big5, который является общим в Гонконге и на Tайване (Republic of China). MySQL big5 в действительности кодовая страница Microsoft 950, которая очень похожа на оригинальный набор символов big5. Пакет перешео на этот набор символов, начиная с MySQL 4.1.16/5.0.16 (в результате Глюка #12476). Например, следующие инструкции работают в текущих версиях MySQL, но не в старых версиях: mysql> CREATE TABLE big5 (BIG5 CHAR(1) CHARACTER SET BIG5); Query OK, 0 rows affected (0.13 sec) mysql> INSERT INTO big5 VALUES (0xf9dc); Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM big5; +------+ | big5 | +------+ | хл¦ | +------+ 1 row in set (0.02 sec) Просьба о добавлении расщирения HKSCS была зарегистрирована. Те, кто нуждается в этом расширении, могут найти интересной предложенную заплатку для Глюка #13577 . 10.11.4: Почему японские преобразования набора символов терпят неудачу? MySQL поддерживает наборы символов sjis, ujis, cp932 и eucjpms так же, как Unicode. Общая потребность состоит в том, чтобы преобразоваться между наборами символов. Например, есть Unix-сервер (обычно с sjis или ujis) и Windows-клиент (а здесь почти всегда встречается cp932). В следующей таблице преобразования столбец ucs2 представляет источник, а столбцы sjis, cp932, ujis и eucjpms представляют адресатов, то есть последние 4 столбца обеспечивают шестнадцатеричный результат, когда Вы используете CONVERT(ucs2) или назначаете столбец, содержащий значение ucs2, столбцу в sjis, cp932, ujis или eucjpms. Имя символа ucs2 sjis cp932 ujis eucjpms BROKEN BAR 00A6 3F 3F 8FA2C3 3F FULLWIDTH BROKEN BAR FFE4 3F FA55 3F 8FA2 YEN SIGN 00A5 3F 3F 20 3F FULLWIDTH YEN SIGN FFE5 818F 818F A1EF 3F TILDE 007E 7E 7E 7E 7E OVERLINE 203E 3F 3F 20 3F HORIZONTAL BAR 2015 815C 815C A1BD A1BD EM DASH 2014 3F 3F 3F 3F REVERSE SOLIDUS 005C 815F 5C 5C 5C FULLWIDTH "" FF3C 3F 815F 3F A1C0 WAVE DASH 301C 8160 3F A1C1 3F FULLWIDTH TILDE FF5E 3F 8160 3F A1C1 DOUBLE VERTICAL LINE 2016 8161 3F A1C2 3F PARALLEL TO 2225 3F 8161 3F A1C2 MINUS SIGN 2212 817C 3F A1DD 3F FULLWIDTH HYPHEN-MINUS FF0D 3F 817C 3F A1DD CENT SIGN 00A2 8191 3F A1F1 3F FULLWIDTH CENT SIGN FFE0 3F 8191 3F A1F1 POUND SIGN 00A3 8192 3F A1F2 3F FULLWIDTH POUND SIGN FFE1 3F 8192 3F A1F2 NOT SIGN 00AC 81CA 3F A2CC 3F FULLWIDTH NOT SIGN FFE2 3F 81CA 3F A2CC Теперь рассмотрите эту часть таблицы: ucs2 sjis cp932 NOT SIGN 00AC 81CA 3F FULLWIDTH NOT SIGN FFE2 3F 81CA Это означает, что MySQL преобразовывает NOT SIGN (Unicode U+00AC) в sjis 0x81CA и в cp932 3F (3F как раз и есть знак вопроса (?), то есть то, что всегда используется, когда преобразование не может выполняться. 10.11.5: Что я должен делать, если я хочу преобразовывать SJIS 81CA в cp932? Имеются серьезные жалобы относительно этого: много людей предпочли бы свободное преобразование так, чтобы 81CA (NOT SIGN) в sjis становился 81CA (FULLWIDTH NOT SIGN) в cp932. Изменение для этого поведения планируется. 10.11.6: Как MySQL представляют знак Yen (Tе)? Проблема возникает потому, что некоторые версии японских наборов символов (sjis и euc) обрабатывают 5C как reverse solidus (\ он же backslash), а другие обрабатывают это как знак йены (Tе). MySQL следует только за одной версией JIS (Japanese Industrial Standards). В MySQL 5C всегда обратный слэш (\). 10.11.7: MySQL планирует делать отдельный набор символов, где 5C представляет знак йены? Это одно из возможных решений для проблемы знака йены, однако, это не будет в MySQL 5.1 или 5.2. 10.11.8: Какие проблемы я должен знать при работе с корейскими наборами символов в MySQL? В теории, хотя есть несколько версий набора символов euckr (Extended Unix Code Korea), только одна проблема была отмечена. Мы используем ASCII-вариант EUC-KR, в котором код 0x5c указывает REVERSE SOLIDUS, \ вместо KS-Roman-варианта EUC-KR, в котором код 0x5c определяет WON SIGN(тВй). Это означает, что Вы не можете преобразовывать Unicode U+20A9 в euckr: mysql> SELECT CONVERT('тВй' USING euckr) AS euckr, – > HEX(CONVERT('тВй' USING euckr)) AS hexeuckr; +-------+----------+ | euckr | hexeuckr | +-------+----------+ | ? | 3F | +-------+----------+ 1 row in set (0.00 sec) Графическая корейская диаграмма MySQL здесь: http://d.udm.net/bar/~bar/charts/euckr_korean_ci.html. 10.11.9: Почему я получаю сообщения об ошибке "Data truncated"? Для иллюстрации мы создадим таблицу с одним столбцом Unicode (ucs2) и другим Chinese (gb2312): mysql> CREATE TABLE ch – > (ucs2 CHAR(3) CHARACTER SET ucs2, – > gb2312 CHAR(3) CHARACTER SET gb2312); Query OK, 0 rows affected (0.05 sec) Мы пробуем помещать редкий символ ц-М в обоих столбцах: mysql> INSERT INTO ch VALUES ('Aц-МB','Aц-МB'); Query OK, 1 row affected, 1 warning (0.00 sec) Имеется предупреждение. Давайте посмотрим, что там случилось: mysql> SHOW WARNINGS; +---------+------+---------------------------------------------+ | Level | Code | Message | +---------+------+---------------------------------------------+ | Warning | 1265 | Data truncated for column 'gb2312' at row 1 | +---------+------+---------------------------------------------+ 1 row in set (0.00 sec) Так что это предупреждение только относительно столбца gb2312. mysql> SELECT ucs2, HEX(ucs2), gb2312, HEX(gb2312) FROM ch; +-------+--------------+--------+-------------+ | ucs2 | HEX(ucs2) | gb2312 | HEX(gb2312) | +-------+--------------+--------+-------------+ | Aц-МB | 00416C4C0042 | A?B | 413F42 | +-------+--------------+--------+-------------+ 1 row in set (0.00 sec) Имеются несколько вещей, которые надлежит понять здесь: Факт, что это является предупреждением, а не ошибкой, характерным для MySQL. Мы предпочитаем пробовать сделать то, что можем, чтобы получить метод наилучшего приближения, чем отказываться. Символ ц-М не находится в наборе символов gb2312. Мы рассматривали эту проблему ранее. По общему признанию сообщение вводит в заблуждение. В этом случае не было никакого усечения: а произошла тривиальная замена символа на вопросительный знак. Авторы уже имели недовольство относительно этого сообщения (см. Глюк #9337 ). Но пока они придумывают кое-что получше, имейте в виду что сообщение 2165 может означать ряд вещей. С SQL_MODE=TRADITIONAL имелось бы сообщение об ошибке, но вместо ошибки 2165 Вы будете видеть: ERROR 1406 (22001): Data too long for column 'gb2312' at row 1. 10.11.10: Почему мой внешний GUI-интерфейс или окно просмотра не отображает символы CJK правильно в моей прикладной программе, использующей Access, PHP или другой API? Получите прямое подключение к серверу, применяя клиент mysql (в Windows: mysql.exe), и попытайтесь выполнить тот же самый запрос там. Если mysql отвечает правильно, то проблема может быть в том, что Ваш интерфейс прикладной программы требует инициализации. Используйте mysql, чтобы понять, какой набор символов это использует с помощью инструкции SHOW VARIABLES LIKE 'char%';. Если Вы используете Access, то Вы наиболее вероятно соединяетесь с MyODBC. В этом случае Вы должны проверить конфигурацию ODBC. Если, например, Вы используете big5, Вы ввели бы SET NAMES 'big5'. Обратите внимание, что ; не требуется в этом случае. Если Вы используете ASP, Вы могли бы добавить SET NAMES в код. Имеется пример, который работал в прошлом: <% Session.CodePage=0 Dim strConnection Dim Conn strConnection="driver={MySQL ODBC 3.51 Driver}; \ server=server;uid=username;" \ "pwd=password; \ database=database; \ stmt=SET NAMES 'big5';" Set Conn = Server.CreateObject("ADODB.Connection") Conn.Open strConnection %> Аналогичным способом, если Вы используете любой набор символов, другой, чем latin1 с Connector/NET, Вы должны определить набор символов в строке подключения. Если Вы используете PHP, опробуйте это: <?php $link = mysql_connect($host, $usr, $pwd); mysql_select_db($db); if (mysql_error()) { print "Database ERROR: " . mysql_error(); } mysql_query("SET NAMES 'utf8'", $link); ?> В этом случае мы использовали SET NAMES, чтобы изменить character_set_client, character_set_connection и character_set_results. Правильно использовать более нового расширения mysqli, а не старого mysql. При использовании mysqli предыдущий пример мог бы быть переписан как показано здесь: <?php $link = new mysqli($host, $usr, $pwd, $db); if (mysqli_connect_errno()) { printf("Connect failed: %s\n", mysqli_connect_error()); exit(); } $link->query("SET NAMES 'utf8'"); ?> Другая проблема, с которой часто сталкиваются в прикладных программах на PHP: что делать с предположениями, сделанными браузером. Иногда добавление или изменение тэга <meta> достаточно, чтобы исправить проблему: например, чтобы обеспечить, чтобы агент пользователя интерпретировал содержание страницы как UTF-8, Вы должны включить <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> в <head> HTML-страницы. 10.11.11: Я обновился до MySQL 5.1. Как я могу возвращаться к поведению, аналогичному MySQL 4.0, относительно наборов символов? В MySQL 4.0 имелся один глобальный набор символов для клиента и сервера, который назначался администратором. Это изменилось в MySQL 4.1. Когда пользователь соединяется, он посылает серверу имя набора символов, который требуется использовать. Сервер использует это имя, чтобы установить переменные системы character_set_client, character_set_results и character_set_connection. В действительности сервер выполняет операцию SET NAMES, использующую имя набора символов. Эффект этого: Вы не можете управлять набором символов пользователя, запуская mysqld с параметром --character-set-server=utf8. Однако, некоторые заказчики сказали, что предпочитают поведение MySQL 4.0. Чтобы делать возможным сохранить это поведение, разработчики добавили в mysqld переключатель --character-set-client-handshake, который может быть выключен с --skip-character-set-client-handshake. Если Вы запускаете mysqld с --skip-character-set-client-handshake, то, когда пользователь соединяется, это посылает серверу имя набора символов, который требуется использовать. Однако, сервер проигнорирует этот запрос от пользователя. Например, предположите, что Ваш любимый набор символов сервера latin1 (вряд ли это так в области CJK, но это значение по умолчанию). Предположите далее, что пользователь использует utf8 потому, что операционная система пользователя поддерживает. Теперь запустите сервер с latin1 как заданный по умолчанию набор символов: mysqld --character-set-server=latin1 Затем запустите пользователя с заданным по умолчанию набором символов utf8: mysql --default-character-set=utf8 Текущие параметры настройки могут быть выяснены, рассматривая вывод SHOW VARIABLES: mysql> SHOW VARIABLES LIKE 'char%'; +--------------------------+----------------------------------------+ | Variable_name | Value | +--------------------------+----------------------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/local/mysql/share/mysql/charsets/ | +--------------------------+----------------------------------------+ 8 rows in set (0.01 sec) Теперь остановите пользователя, а затем и сервер, используя mysqladmin. Затем запустите сервер снова, но на сей раз сообщите, чтобы он не менял набор символов: mysqld --character-set-server=utf8 --skip-character-set-client-handshake Запустите пользователя с utf8 еще раз как заданный по умолчанию набор символов, а затем отобразите текущие параметры настройки: mysql> SHOW VARIABLES LIKE 'char%'; +--------------------------+----------------------------------------+ | Variable_name | Value | +--------------------------+----------------------------------------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/local/mysql/share/mysql/charsets/ | +--------------------------+----------------------------------------+ 8 rows in set (0.01 sec) Как Вы можете видеть, сравнивая отличия выводов SHOW VARIABLES, сервер игнорирует начальные установки пользователя, если используется опция --skip-character-set-client-handshake. 10.11.12: Почему некоторые LIKE и поиск FULLTEXT с символами CJK срываются? Имеется очень простая проблема с поисками LIKE на столбцах BINARY и BLOB: мы должны знать конец символа. С многобайтовыми наборами символов, различные символы могли бы иметь различные длины. Например, в utf8, A требует один байт, но уГЪ требует трех байтов, как показано здесь: +-------------------------+---------------------------+ | OCTET_LENGTH(_utf8 'A') | OCTET_LENGTH(_utf8 'уГЪ') | +-------------------------+---------------------------+ | 1 | 3 | +-------------------------+---------------------------+ 1 row in set (0.00 sec) Если мы не знаем, где символьные концы, то мы не знаем, где начинаются следующие символы даже в очень простых поисках, типа LIKE '_A%'. Решение состоит в том, чтобы использовать регулярный набор символов CJK или преобразовываться в набор символов CJK перед сравнением. Это одна причина, почему MySQL не может позволять кодирование несуществующих символов. Если это не строго относительно отклонения, то не имеется никакого способа узнавать, где символы заканчиваются. Для поисков FULLTEXT мы должны знать, где слова начинаются и заканчиваются. С западными языками это редко проблема, потому что большинство (если не все) они используют пробел, чтобы идентифицировать конец слова. Однако, это не так с азиатской записью. 10.11.13: Какие наборы символов CJK доступны в MySQL? Список наборов символов CJK может изменяться в зависимости от Вашей версии MySQL. Например, набор символов eucjpms не обеспечивался до MySQL 5.0.3. Однако, так как имя соответствующего языка появляется в столбце DESCRIPTION для каждого входа в таблице INFORMATION_SCHEMA.CHARACTER_SETS, Вы можете получать текущий список всех не-Unicode наборов символов CJK, используя этот запрос: mysql> SELECT CHARACTER_SET_NAME, DESCRIPTION FROM – > INFORMATION_SCHEMA.CHARACTER_SETS – > WHERE DESCRIPTION LIKE '%Chinese%' OR – > DESCRIPTION LIKE '%Japanese%' OR DESCRIPTION LIKE '%Korean%' – > ORDER BY CHARACTER_SET_NAME; +--------------------+---------------------------+ | CHARACTER_SET_NAME | DESCRIPTION | +--------------------+---------------------------+ | big5 | Big5 Traditional Chinese | | cp932 | SJIS for Windows Japanese | | eucjpms | UJIS for Windows Japanese | | euckr | EUC-KR Korean | | gb2312 | GB2312 Simplified Chinese | | gbk | GBK Simplified Chinese | | sjis | Shift-JIS Japanese | | ujis | EUC-JP Japanese | +--------------------+---------------------------+ 8 rows in set (0.01 sec) 10.11.14: Как я узнаю, является ли символ X доступным во всех наборах символов? Большинство упрощеннных китайских и японских символов Kana появляются во всех CJK-наборах символов. Эта сохраненная процедура принимает символ UCS-2 Unicode, преобразует это во все другие наборы символов и отображает результаты в шестнадцатеричном формате. DELIMITER // CREATE PROCEDURE p_convert(ucs2_char CHAR(1) CHARACTER SET ucs2) BEGIN CREATE TABLE tj (ucs2 CHAR(1) character set ucs2, utf8 CHAR(1) character set utf8, big5 CHAR(1) character set big5, cp932 CHAR(1) character set cp932, eucjpms CHAR(1) character set eucjpms, euckr CHAR(1) character set euckr, gb2312 CHAR(1) character set gb2312, gbk CHAR(1) character set gbk, sjis CHAR(1) character set sjis, ujis CHAR(1) character set ujis); INSERT INTO tj (ucs2) VALUES (ucs2_char); UPDATE tj SET utf8=ucs2, big5=ucs2, cp932=ucs2, eucjpms=ucs2, euckr=ucs2, gb2312=ucs2, gbk=ucs2, sjis=ucs2, ujis=ucs2; /* If there's a conversion problem, UPDATE will produce a warning. */ SELECT hex(ucs2) AS ucs2, hex(utf8) AS utf8, hex(big5) AS big5, hex(cp932) AS cp932, hex(eucjpms) AS eucjpms, hex(euckr) AS euckr, hex(gb2312) AS gb2312, hex(gbk) AS gbk, hex(sjis) AS sjis, hex(ujis) AS ujis FROM tj; DROP TABLE tj; END// Ввод может быть любым одиночным символом ucs2 или значением отметки кода (шестнадцатеричное представление) для этого символа. Например, из списка Unicode кодирования и имен ucs2 ( http://www.unicode.org/Public/UNIDATA/UnicodeData.txt) мы знаем, что символ Katakana Pe появляется во всех CJK-наборах символов, и что значение отметки кода 0x30da. Если мы используем это значение как параметр для p_convert(), результат показывается здесь: mysql> CALL p_convert(0x30da)// +------+--------+------+-------+---------+-----+------+------+------+------+ | ucs2 | utf8 | big5 | cp932 | eucjpms |euckr|gb2312| gbk | sjis | ujis | +------+--------+------+-------+---------+-----+------+------+------+------+ | 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 t\G ******************** 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%'; +---------+---------------+-------------------+--------+ | Charset | Description | Default collation | Maxlen | +---------+---------------+-------------------+--------+ | ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 | +---------+---------------+-------------------+--------+ 1 row in set (0.00 sec) Для ucs2 и utf8 заданное по умолчанию объединение: general. Чтобы определять объединение Unicode, используйте COLLATE ucs2_unicode_ci. 10.11.17: Почему мои дополнительные символы отклонены MySQL? MySQL не поддерживает дополнительные символы, то есть символы, которые нуждаются больше, чем в 3 байтах для UTF-8. Пакет поддерживает только Basic Multilingual Plane/Plane 0 . Только несколько очень редких символов Han дополнительны; поддержка для них необыкновенна. Это привело к отчетам типа найденного в Глюке #12600, который авторы отклонили как не ошибка. С utf8 мы должны усечь входную строку, когда сталкиваемся с байтами, которые не понимаем. Иначе мы не знали бы, какой длины многобайтовый символ. Одно возможное решение должно использовать ucs2 вместо utf8, когда символы изменены на вопросительные знаки. Однако, никакое усечение не происходит. Вы можете также изменять тип данных на BLOB или BINARY, которые не выполняют никакую проверку правильности. 10.11.18: Разве это не должен быть CJKV? Нет. Термин CJKV (Chinese Japanese Korean Vietnamese) обращается к вьетнамским наборам символов, которые содержат Han (изначально китайские) символы. MySQL не имеет никакого плана, чтобы поддерживать старый вьетнамский вариант, использующий символы Han. MySQL поддерживает современный вьетнамский вариант с символами Western. Глюк #4745 просьба о специализированном вьетнамском объединении, которое может быть добавлено в будущем, если имеется достаточная потребность в этом. 10.11.19: MySQL позволяет символам CJK использоваться в именах баз данных и таблиц? Эта проблема отфиксирована в MySQL 5.1, автоматически переписывая имена соответствующих каталогов и файлов. Например, если Вы создаете базу данных цео на сервере, чья операционная система не поддерживает CJK в именах каталогов, MySQL создает каталог @0w@00a5@00ae, который является только причудливым способом кодирования E6A5AE, то есть шестнадцатеричное представление для Unicode-символа цео. Однако, если Вы выполняете инструкцию SHOW DATABASES, Вы можете видеть, что база данных перечислена как цео. 10.11.20: Где я могу находить переводы руководства по MySQL на китайский, корейский и японский языки? Упрощенная китайская версия руководства для MySQL 5.1.12 может быть найдена на http://dev.mysql.com/doc/#chinese-5.1. Японская для MySQL 4.1 может быть получена с http://dev.mysql.com/doc/#japanese-4.1. 10.11.21: Где я могу получать справку по CJK и связанным проблемам в MySQL? Следующие ресурсы доступны: Перечень групп пользователей MySQL может быть найден на http://dev.mysql.com/user-groups/. Вы можете входить в контакт с инженером сбыта в MySQL KK Japan: Tel: +81(0)3-5326-3133 Fax: +81(0)3-5326-3001 Email: dsaito@mysql.com Просмотр показывает запросы в отношении проблем набора символов на http://tinyurl.com/y6xcuf. Посетите форум "MySQL Character Sets, Collation, Unicode" на http://forums.mysql.com/list.php?103. |
|
||
Главная | Контакты | Нашёл ошибку | Прислать материал | Добавить в избранное |
||||
|