Spec-Zone.ru › MySQL 5.7

A.11 MySQL 5.7 FAQ: MySQL Китайские, японские и корейские наборы символов

Этот набор часто задаваемых вопросов составлен на основе опыта групп поддержки и разработки MySQL по обработке многочисленных запросов о проблемах с наборами символов CJK (китайские, японские и корейские).

A.11.1. Какие наборы символов CJK доступны в MySQL?
A.11.2. Я вставил символы CJK в свою таблицу. Почему при SELECT они отображаются как символы «?»?
A.11.3. С какими проблемами следует ознакомиться при работе с китайским набором символов Big5?
A.11.4. Почему происходит сбой преобразования японских наборов символов?
A.11.5. Что мне делать, если я хочу преобразовать SJIS 81CA в cp932?
A.11.6. Как MySQL представляет символ иены (¥)?
A.11.7. С какими проблемами следует ознакомиться при работе с корейскими наборами символов в MySQL?
A.11.8. Почему появляются сообщения об ошибке «Неверное значение строки»?
A.11.9. Почему в моём графическом интерфейсе или браузере символы CJK отображаются неправильно в приложении, использующем Access, PHP или другой API?
A.11.10. Я перешел на MySQL 5.7. Как можно вернуть поведение MySQL 4.0 в отношении наборов символов?
A.11.11. Почему некоторые запросы LIKE и FULLTEXT с символами CJK завершаются ошибкой?
A.11.12. Как узнать, доступен ли символ X во всех наборах символов?
A.11.13. Почему строки CJK сортируются неправильно в Unicode? (I)
A.11.14. Почему строки CJK сортируются неправильно в Unicode? (II)
A.11.15. Почему MySQL отклоняет мои дополнительные символы?
A.11.16. Следует ли использовать «CJKV» вместо «CJK»?
A.11.17. Разрешает ли MySQL использование символов CJK в именах баз данных и таблиц?
A.11.18. Где я могу найти переводы руководства MySQL на китайский, японский и корейский языки?
A.11.19. Где я могу получить помощь по вопросам CJK и связанных проблем в MySQL?

A.11.1.

Какие наборы символов CJK доступны в MySQL?

Список наборов символов CJK может отличаться в зависимости от версии MySQL. Например, набор символов gb18030 не поддерживается до MySQL 5.7.4. Однако, поскольку имя соответствующего языка отображается в столбце DESCRIPTION для каждой записи в таблице INFORMATION_SCHEMA.CHARACTER_SETS, вы можете получить текущий список всех наборов символов CJK, не использующих Unicode, используя этот запрос:

mysql> SELECT CHARACTER_SET_NAME, DESCRIPTION
       FROM INFORMATION_SCHEMA.CHARACTER_SETS
       WHERE DESCRIPTION LIKE '%Chin%'
       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                   |
| gb18030            | China National Standard GB18030 |
| gb2312             | GB2312 Simplified Chinese       |
| gbk                | GBK Simplified Chinese          |
| sjis               | Shift-JIS Japanese              |
| ujis               | EUC-JP Japanese                 |
+--------------------+---------------------------------+

(Для получения дополнительной информации см. Раздел 24.3.2, «Таблица INFORMATION_SCHEMA CHARACTER_SETS».)

MySQL поддерживает три варианта наборов символов GB (Guojia Biaozhun, или Национальный стандарт, или Упрощённый китайский), которые являются официальными в КНР: gb2312, gbk и (начиная с MySQL 5.7.4) gb18030.

Иногда люди пытаются вставить символы gbk в gb2312, и это работает в большинстве случаев, потому что gbk является супермножеством gb2312. Но в конечном итоге они пытаются вставить более редкий китайский символ, и это не работает. (Для примера см. баг #16072).

Здесь мы пытаемся уточнить, какие именно символы являются допустимыми в gb2312 или gbk, со ссылкой на официальные документы. Пожалуйста, проверьте эти ссылки перед сообщением о ошибках gb2312 или gbk:

  • Набор символов MySQL gbk фактически является “кодовой страницей Microsoft 936”. Это отличается от официального gbk для символов A1A4 (средняя точка), A1AA (длинное тире), A6E0-A6F5 и A8BB-A8C0.

  • Список соответствий gbk/Unicode см. в http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT.

Также возможно хранение символов CJK в наборах символов Unicode, хотя доступные правила сортировки могут не сортировать символы так, как вы ожидаете:

  • Наборы символов utf8 и ucs2 поддерживают символы из базовой многоязычной плоскости Unicode (BMP). Эти символы имеют значения кодов между U+0000 и U+FFFF.

  • Наборы символов utf8mb4, utf16, utf16le и utf32 поддерживают символы BMP, а также дополнительные символы, которые находятся за пределами BMP. Дополнительные символы имеют значения кодов между U+10000 и U+10FFFF.

Используемое правило сортировки для набора символов Unicode определяет возможность сортировки (то есть различения) символов в наборе:

  • Правила сортировки, основанные на алгоритме сортировки Unicode (UCA) 4.0.0, различают только символы BMP.

  • Правила сортировки, основанные на UCA 5.2.0 или 9.0.0, различают символы BMP и дополнительные символы.

  • Правила сортировки, не основанные на UCA, могут не различать все символы Unicode. Например, по умолчанию в utf8mb4 используется правило сортировки utf8mb4_general_ci, которое различает только символы BMP.

Кроме того, различие символов не равнозначно их упорядочиванию в соответствии с правилами конкретного языка CJK. В настоящее время MySQL имеет только одно правило сортировки UCA для CJK, gb18030_unicode_520_ci (которое требует использования набора символов без Unicode gb18030).

Сведения о правилах сортировки Unicode и их свойствах различия, включая свойства сортировки дополнительных символов, см. в Раздел 10.10.1, «Наборы символов Unicode».

A.11.2.

Я вставил символы 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 в качестве результата?

    Например, японский катакана-символ Pe (ペ') существует во всех наборах символов CJK и имеет значение кода (шестнадцатеричное кодирование) 0x30da. Для проверки циклического прохода для этого символа используйте этот запрос:

    SELECT 'ペ' AS `ペ`;         /* or SELECT _ucs2 0x30da; */
    

    Если результатом не является также ペ, циклический проход не удался.

    При сообщениях об ошибках таких сбоев мы можем попросить вас предоставить дополнительные сведения SELECT HEX('ペ');. Тогда мы сможем определить, является ли кодировка клиента корректной.

  • Убедитесь, что проблема не в браузере или другом приложении, а не в MySQL.

    Используйте программу-клиент mysql для выполнения этой задачи. Если программа 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/ |
    +--------------------------+----------------------------------------+
    

    Это типичные настройки набора символов для международного клиента (обратите внимание на использование utf8 Unicode), подключённого к серверу в Западной Европе (latin1 — набор символов Западной Европы).

    Хотя Unicode (обычно вариант utf8 в Unix и вариант ucs2 в Windows) предпочтительнее латинского, он не всегда лучше поддерживается утилитами вашей операционной системы. Многие пользователи Windows обнаруживают, что набор символов Microsoft, такой как cp932 для японской Windows, подходит.

    Если вы не можете контролировать настройки сервера и не знаете, какие настройки использует ваш компьютер, попробуйте изменить их на общий набор символов для вашей страны (euckr = Корея; gb18030, gb2312 или gbk = Китайская Народная Республика; big5 = Тайвань; sjis, ujis, cp932 или eucjpms = Япония; ucs2 или utf8 = любая другая). Обычно необходимо изменить только настройки клиента, подключения и результатов. Оператор SET NAMES изменяет все три сразу. Например:

    SET NAMES 'big5';
    

    После того, как настройка будет правильной, её можно сделать постоянной, отредактировав my.cnf или my.ini. Например, вы можете добавить строки, похожие на эти:

    [mysqld]
    character-set-server=big5
    [client]
    default-character-set=big5
    

    Также возможно, что проблемы возникают из-за настроек API, используемых в вашем приложении; для получения дополнительной информации см. Почему мой интерфейс GUI или браузер не отображает правильно символы CJK...?

A.11.3.

Какие проблемы следует учитывать при работе с набором символов Big5 для китайского языка?

MySQL поддерживает набор символов Big5, который распространён в Гонконге и на Тайване (Китайская Республика). Набор символов MySQL big5 фактически представляет собой кодовую страницу Microsoft 950, которая очень похожа на исходный набор символов big5.

Была подана заявка на добавление расширений HKSCS. Пользователи, которым необходимо это расширение, могут найти предложенную исправление для ошибки #13577.

A.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
РАЗРЫВ ШТРИХА 00A6 3F 3F 8FA2C3 3F
РАЗРЫВ ШТРИХА (ПОЛНАЯ ШИРИНА) FFE4 3F FA55 3F 8FA2
ЗНАК ИЕНЫ 00A5 3F 3F 20 3F
ЗНАК ИЕНЫ (ПОЛНАЯ ШИРИНА) FFE5 818F 818F A1EF 3F
ТИЛЬДА 007E 7E 7E 7E 7E
НАДСТРОЧНАЯ ЛИНИЯ 203E 3F 3F 20 3F
ГОРИЗОНТАЛЬНАЯ ЛИНИЯ 2015 815C 815C A1BD A1BD
ТИРЕ 2014 3F 3F 3F 3F
ОБРАТНЫЙ СЛЁШ 005C 815F 5C 5C 5C
ОБРАТНЫЙ СЛЁШ (ПОЛНАЯ ШИРИНА) FF3C 3F 815F 3F A1C0
ВОЛНА 301C 8160 3F A1C1 3F
ТИЛЬДА (ПОЛНАЯ ШИРИНА) FF5E 3F 8160 3F A1C1
ДВОЙНАЯ ВЕРТИКАЛЬНАЯ ЛИНИЯ 2016 8161 3F A1C2 3F
ПАРАЛЛЕЛЬНО 2225 3F 8161 3F A1C2
МИНУС 2212 817C 3F A1DD 3F
МИНУС (ПОЛНАЯ ШИРИНА) FF0D 3F 817C 3F A1DD
ЦЕНТ 00A2 8191 3F A1F1 3F
ЦЕНТ (ПОЛНАЯ ШИРИНА) FFE0 3F 8191 3F A1F1
ФУНТ 00A3 8192 3F A1F2 3F
ФУНТ (ПОЛНАЯ ШИРИНА) FFE1 3F 8192 3F A1F2
НЕ 00AC 81CA 3F A2CC 3F
НЕ (ПОЛНАЯ ШИРИНА) FFE2 3F 81CA 3F A2CC

Теперь рассмотрим следующую часть таблицы.

ucs2 sjis cp932
НЕ 00AC 81CA 3F
НЕ (ПОЛНАЯ ШИРИНА) FFE2 3F 81CA

Это означает, что MySQL преобразует NOT SIGN (Unicode U+00AC) в sjis код 0x81CA и в cp932 код 3F. (3F — это знак вопроса (“?”. Это используется всегда, когда преобразование невозможно).

A.11.5.

Что мне делать, если я хочу преобразовать SJIS 81CA в cp932?

Наш ответ: “?”. Это имеет недостатки, и многие предпочли бы «мягкое» преобразование, чтобы 81CA (NOT SIGN) в sjis стал 81CA (FULLWIDTH NOT SIGN) в cp932.

A.11.6.

Как MySQL представляет знак иены (¥)?

Проблема возникает, потому что некоторые версии японских наборов символов (как sjis, так и euc) рассматривают 5C как обратный слэш (reverse solidus, \), а другие как знак иены (¥).

MySQL использует только одну версию описания стандарта JIS (Японские промышленные стандарты). В MySQL, 5C всегда представляет собой обратный слэш (\).

A.11.7.

Какие проблемы следует учитывать при работе с корейскими наборами символов в MySQL?

Теоретически, хотя было несколько версий набора символов EUC-KR (Extended Unix Code Korea), отмечена только одна проблема. Мы используем вариант EUC-KR “ASCII”, в котором код 0x5c является ОБРАТНЫМ СЛЁШОМ, то есть \, вместо варианта “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       |
+-------+----------+

A.11.8.

Почему появляются сообщения об ошибке Incorrect string value?

Для демонстрации проблемы создайте таблицу с одним столбцом Unicode (ucs2) и одним столбцом китайского (gb2312) языка.

mysql> CREATE TABLE ch
       (ucs2 CHAR(3) CHARACTER SET ucs2,
       gb2312 CHAR(3) CHARACTER SET gb2312);

В режиме SQL без жёстких ограничений попробуйте поместить редкий символ 汌 в оба столбца.

mysql> SET sql_mode = '';
mysql> INSERT INTO ch VALUES ('A汌B','A汌B');
Query OK, 1 row affected, 1 warning (0.00 sec)

INSERT генерирует предупреждение. Используйте следующее утверждение, чтобы узнать о нём:

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Warning
   Code: 1366
Message: Incorrect string value: '\xE6\xB1\x8CB' for column 'gb2312' at row 1

Таким образом, это предупреждение только о столбце gb2312.

mysql> SELECT ucs2,HEX(ucs2),gb2312,HEX(gb2312) FROM ch;
+-------+--------------+--------+-------------+
| ucs2  | HEX(ucs2)    | gb2312 | HEX(gb2312) |
+-------+--------------+--------+-------------+
| A汌B | 00416C4C0042 | A?B    | 413F42      |
+-------+--------------+--------+-------------+

Здесь требуется несколько объяснений:

  1. Символ 汌 отсутствует в наборе символов gb2312, как описано ранее.

  2. Если вы используете старую версию MySQL, вы можете увидеть другое сообщение.

  3. Возникает предупреждение, а не ошибка, потому что режим SQL без жёстких ограничений не активен. В режиме без жёстких ограничений MySQL пытается выполнить оптимальное преобразование, а не прекращать его. При жёстких ограничениях сообщение об ошибке Incorrect string value выводится в качестве ошибки, а не предупреждения, и INSERT не выполняется.

A.11.9.

Почему в вашем приложении, использующем Access, PHP или другой API, CJK-символы отображаются неправильно в пользовательском интерфейсе или браузере?

Получите прямое подключение к серверу с помощью клиента mysql и попробуйте тот же запрос там. Если mysql отвечает правильно, проблема может быть в том, что интерфейс вашего приложения требует инициализации. Используйте mysql, чтобы узнать, какой набор символов или наборы символов он использует с оператором SHOW VARIABLES LIKE 'char%';. Если вы используете Access, вы, скорее всего, подключаетесь с помощью Connector/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 = new mysqli($host, $usr, $pwd, $db);

  if( mysqli_connect_errno() )
  {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
  }

  $link->query("SET NAMES 'utf8'");
?>

В этом случае мы использовали SET NAMES для изменения character_set_client, character_set_connection и character_set_results.

Другая проблема, часто встречающаяся в приложениях PHP, связана с предположениями, которые делает браузер. Иногда добавление или изменение тега <meta> достаточно для исправления проблемы: например, чтобы убедиться, что пользовательский агент интерпретирует содержимое страницы как UTF-8, включите <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> в раздел <head> HTML-страницы.

Если вы используете Connector/J, см. .

A.11.10.

Я обновился до MySQL 5.7. Как я могу вернуться к поведению, подобному MySQL 4.0, в отношении наборов символов?

В MySQL версии 4.0 был единственный “глобальный” набор символов для сервера и клиента, и решение о том, какой набор символов использовать, принимал администратор сервера. Это изменилось начиная с MySQL версии 4.1. Теперь происходит “рукопожатие”, как описано в разделе 10.4, «Наборы символов и кодовые страницы подключения»:

Когда клиент подключается, он отправляет серверу имя набора символов, который он хочет использовать. Сервер использует это имя для установки системных переменных 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. Предположим также, что клиент использует 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/ |
+--------------------------+----------------------------------------+

Теперь остановите клиент и сервер, используя 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/ |
+--------------------------+----------------------------------------+

Как видно из различных результатов SHOW VARIABLES, сервер игнорирует начальные настройки клиента, если используется опция --skip-character-set-client-handshake.

A.11.11.

Почему некоторые поиски LIKE и FULLTEXT с символами CJK терпят неудачу?

Для поисков LIKE есть очень простая проблема с типами столбцов бинарных строк, такими как BINARY и BLOB: мы должны знать, где заканчиваются символы. В многобайтовых наборах символов разные символы могут иметь различную длину октета. Например, в utf8, A требует один байт, но ペ требует три байта, как показано здесь:

+-------------------------+---------------------------+
| OCTET_LENGTH(_utf8 'A') | OCTET_LENGTH(_utf8 'ペ') |
+-------------------------+---------------------------+
|                       1 |                         3 |
+-------------------------+---------------------------+

Если мы не знаем, где заканчивается первый символ в строке, мы не знаем, где начинается второй символ, в этом случае даже очень простые запросы, такие как LIKE '_A%', терпят неудачу. Решение состоит в использовании типа столбца небинарных строк, определённого с соответствующим набором символов CJK. Например: mycol TEXT CHARACTER SET sjis. В качестве альтернативы можно преобразовать в набор символов CJK перед сравнением.

Это одна из причин, по которой MySQL не может допускать кодировки несуществующих символов. Если он не строг в отношении отклонения некорректного ввода, он не может определить, где заканчиваются символы.

Для FULLTEXT поисков мы должны знать, где начинаются и заканчиваются слова. В западных языках это редко проблема, потому что большинство (если не все) из них используют легко определяемые границы слов: пробел. Однако это обычно не так с азиатскими письменностями. Мы могли бы использовать произвольные промежуточные меры, например, предполагать, что все символы Хан представляют собой слова, или (для японского языка) зависеть от изменений от катаканы к хирагане из-за грамматических окончаний. Однако единственное надёжное решение требует комплексного словаря, что означает, что нам нужно будет включить словарь в сервер для каждого азиатского языка. Это просто непрактично.

A.11.12.

Как узнать, доступен ли символ X во всех наборах символов?

Большинство упрощённых китайских и базовых неполноширинных японских кана встречаются во всех наборах символов CJK. Следующая хранимая процедура принимает символ Unicode UCS-2, преобразует его в другие наборы символов и отображает результаты в шестнадцатеричном формате.

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 are conversion problems, UPDATE produces warnings. */

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//

DELIMITER ;

Вход может быть любым одиночным ucs2 символом или его кодовым значением (шестнадцатеричным представлением). Например, из списка кодировок и названий Unicode (http://www.unicode.org/Public/UNIDATA/UnicodeData.txt) известно, что символ катаканы Pe присутствует во всех наборах символов CJK, а его кодовое значение равно X'30DA'. Если мы используем это значение в качестве аргумента для p_convert(), результат будет таким:

mysql> CALL p_convert(X'30DA');
+------+--------+------+-------+---------+-------+--------+------+------+------+
| ucs2 | utf8   | big5 | cp932 | eucjpms | euckr | gb2312 | gbk  | sjis | ujis |
+------+--------+------+-------+---------+-------+--------+------+------+------+
| 30DA | E3839A | C772 | 8379  | A5DA    | ABDA  | A5DA   | A5DA | 8379 | A5DA |
+------+--------+------+-------+---------+-------+--------+------+------+------+

Поскольку ни одно из значений столбца не равно 3F (то есть символу вопроса, ?), мы знаем, что все преобразования прошли успешно.

A.11.13.

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

Примечание

Описанные здесь проблемы сортировки CJK могут возникать в версиях MySQL, предшествующих MySQL 8.0. Начиная с MySQL 8.0, их можно решить, используя кодировку utf8mb4 и сортировку utf8mb4_ja_0900_as_cs.

Иногда пользователи замечают, что результат поиска utf8_unicode_ci или ucs2_unicode_ci, или сортировки ORDER BY не соответствует тому, что, по их мнению, ожидал бы носитель языка. Хотя мы никогда не исключаем возможности наличия ошибки, в прошлом мы обнаружили, что многие люди неверно читают стандартную таблицу весов для алгоритма сортировки Unicode. MySQL использует таблицы, расположенные по адресу http://www.unicode.org/Public/UCA/:

  • Таблица UCA 4.0.0: http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt

    Это включает в себя сортировки xxx_unicode_ci без номера версии в имени сортировки.

  • Таблица UCA 5.2.0: http://www.unicode.org/Public/UCA/5.2.0/allkeys.txt

    Это включает в себя сортировки с _520_ в имени сортировки.

  • Таблица UCA 9.0.0: http://www.unicode.org/Public/UCA/9.0.0/allkeys.txt

    Это включает в себя сортировки с _0900_ в имени сортировки.

Для обработки новых версий UCA мы создаем новые сортировки. Мы очень осторожны в отношении изменения порядка существующих сортировок, поскольку это влияет на индексы, что может привести к ситуациям, подобным описанной в ошибке #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   |
+------+
| が  |
| か  |
+------+

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

mysql> SELECT s1, HEX(CONVERT(s1 USING ucs2)) FROM tj;
+------+-----------------------------+
| s1   | HEX(CONVERT(s1 USING ucs2)) |
+------+-----------------------------+
| が  | 304C                        |
| か  | 304B                        |
+------+-----------------------------+

Теперь мы ищем 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, которые являются звонкими и глухими компонентами одной и той же пары букв). Что более важно, основной вес (первое шестнадцатеричное число в квадратных скобках) равен 1E57 в обеих строках. При сравнении как при поиске, так и при сортировке MySQL учитывает только основной вес, игнорируя все остальные числа. Это означает, что мы сортируем が и か правильно в соответствии со спецификацией Unicode. Если бы мы хотели различить их, нам пришлось бы использовать сортировку, отличную от UCA (алгоритм сортировки Unicode) (utf8_bin или utf8_general_ci), или сравнить значения HEX(), или использовать ORDER BY CONVERT(s1 USING sjis). Быть правильным “в соответствии с Unicode”, конечно, недостаточно: человек, сообщивший об ошибке, был так же прав. Чтобы решить это, нам нужна другая сортировка для японского языка в соответствии со стандартом JIS X 4061, в котором звонкие/глухие пары букв, такие как KA/GA, различимы для целей упорядочивания.

A.11.14.

Почему строки CJK сортируются неправильно в Unicode? (II)

Примечание

Описанные здесь проблемы сортировки CJK могут возникать в версиях MySQL, предшествующих MySQL 8.0. Начиная с MySQL 8.0, их можно решить, используя кодировку utf8mb4 и сортировку utf8mb4_ja_0900_as_cs.

Если вы используете Unicode (ucs2 или utf8) и знаете, какой порядок сортировки Unicode используется (см. Раздел A.11, «MySQL 5.7 FAQ: Наборы символов MySQL для китайского, японского и корейского языков»), но 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

Поскольку кодировка для столбца s1, по-видимому, верна (ucs2), проверьте, какую информацию может предоставить таблица 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 |
+-------------+--------------------+-----------------+

(См. Раздел 24.3.5, «Таблица INFORMATION_SCHEMA COLUMNS» для получения дополнительной информации.)

Вы можете видеть, что сортировка — это ucs2_general_ci вместо ucs2_unicode_ci. Причину этого можно найти с помощью SHOW CHARACTER SET, как показано здесь:

mysql> SHOW CHARSET LIKE 'ucs2%';
+---------+---------------+-------------------+--------+
| Charset | Description   | Default collation | Maxlen |
+---------+---------------+-------------------+--------+
| ucs2    | UCS-2 Unicode | ucs2_general_ci   |      2 |
+---------+---------------+-------------------+--------+

Для ucs2 и utf8 сортировка по умолчанию — “general”. Чтобы указать сортировку Unicode UCA, используйте COLLATE ucs2_unicode_ci, как показано в предыдущем пункте.

A.11.15.

Почему мои дополнительные символы отклоняются MySQL?

Дополнительные символы находятся за пределами базовой многоязыковой плоскости/плоскости 0 Unicode. Символы BMP имеют значения кодовых точек от U+0000 до U+FFFF. Дополнительные символы имеют значения кодовых точек от U+10000 до U+10FFFF.

Для хранения дополнительных символов необходимо использовать кодировку, которая их поддерживает:

  • Кодировки utf8 и ucs2 поддерживают только символы BMP.

    Кодировка utf8 допускает только UTF-8 символы, занимающие до трех байтов. Это привело к сообщениям, таким как сообщение об ошибке #12600, которое мы отклонили как “не ошибка”. С utf8 MySQL должен усекать входную строку при обнаружении байтов, которые он не понимает. В противном случае неизвестно, насколько длинным является неправильный многобайтовый символ.

    Одним из возможных обходных путей является использование ucs2 вместо utf8, в этом случае “неправильные” символы заменяются вопросительными знаками. Однако усечение не происходит. Вы также можете изменить тип данных на BLOB или BINARY, которые не выполняют проверку допустимости.

  • Кодировки utf8mb4, utf16, utf16le и utf32 поддерживают символы BMP, а также дополнительные символы за пределами BMP.

A.11.16.

Должно ли “CJK” быть “CJKV”?

Нет. Термин “CJKV” (китайский японский корейский вьетнамский) относится к вьетнамским кодировкам, которые содержат иероглифы Хан (первоначально китайские). MySQL поддерживает современный вьетнамский алфавит с западными символами, но не поддерживает старый вьетнамский алфавит с использованием иероглифов Хан.

Начиная с MySQL 5.6, существуют вьетнамские сортировки для кодировок Unicode, как описано в Разделе 10.10.1, «Кодировки Unicode».

A.11.17.

Разрешает ли MySQL использование символов CJK в именах баз данных и таблиц?

Да.

A.11.18.

Где я могу найти переводы руководства MySQL на китайский, японский и корейский языки?

Японский перевод руководства MySQL 5.6 можно загрузить с https://dev.mysql.com/doc/.

A.11.19.

Где я могу получить помощь по проблемам CJK и связанным с ними проблемам в MySQL?

Доступны следующие ресурсы:

  • Список групп пользователей MySQL можно найти по адресу https://wikis.oracle.com/display/mysql/List+of+MySQL+User+Groups.

  • Просмотреть запросы на новые функции, связанные с проблемами набора символов, можно по адресу http://tinyurl.com/y6xcuf.

  • Посетите форум MySQL Character Sets, Collation, Unicode Forum. http://forums.mysql.com/ также предоставляет форумы на иностранных языках.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/faqs-cjk.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API