The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

Каталог документации / Раздел "Базы данных, SQL" / Оглавление документа
Глава 10. Поддержка наборов символов

MySQL включает поддержку набора символов, которая дает возможность Вам сохранить данные, использующие ряд наборов символов и выполнять сравнения согласно ряду объединений. Вы можете определять наборы символов на уровне сервера, базы данных, таблицы и столбца. MySQL поддерживает использование наборов символов для типов хранения MyISAM, MEMORY, NDBCluster и InnoDB.

Эта глава обсуждает следующие темы

Проблемы набора символов воздействуют на хранение данных, но также и на связь между программами пользователя и сервером MySQL. Если Вы хотите, чтобы программа пользователя связалась с сервером, использующим набор символов, отличный от значения по умолчанию, вы должны будете указать, который именно. Например, чтобы использовать utf8 Unicode, выдайте эту инструкцию после соединения с сервером:

SET NAMES 'utf8';

10.1. Наборы символов и объединения вообще

Набор символов представляет собой множество символов и их кодов. Объединение задает набор правил для сравнения символов в наборе символов. Давайте сделаем различие явным с помощью примера.

Предположите, что мы имеем алфавит с четырьмя символами: A, B, a, b. Мы даем каждому символу номер: A = 0, B = 1, a = 2, b = 3. Символ A имеет номер 0, который the кодирует символ A, комбинация из всех четырех символов и их кодирования как раз и есть набор символов.

Предположите, что мы хотим сравнивать два строковых значения, A и B. Самый простой способ сделать это состоит в том, чтобы рассмотреть кодирование: 0 = A и 1 = B. Поскольку 0 меньше чем 1, мы говорим, что A меньше чем B. Что мы только что сделали? Применили объединение к нашему набору символов. Объединение задает набор правил (только одно правило в этом случае). Самым простым из всех возможных объединений является двоичное объединение.

Но что, если мы хотим считать, что нижний регистр и прописные буквы эквивалентны? Мы имели бы по крайней мере два правила: (1) обрабатывает символы нижнего регистра a и b как эквивалент A и B, (2) затем сравнивает кодирование. Мы называем это объединением без учета регистра. Это немного более сложно, чем двоичное объединение.

В реальной жизни большинство наборов символов имеет много символов: не только A и B, а целые алфавиты, иногда много алфавитов или восточные системы записи с тысячами символов, наряду с многими специальными символами и знаками препинания. Также в реальной жизни большинство объединений имеет много правил, не только для того, чтобы отличить регистр символов, но также и для того, чтобы отличить диакритические знаки. А также для многосимвольных отображений (типа правил в немецком языке).

MySQL может делать эти дела для Вас:

В этих отношениях MySQL далек от большинства других систем управления базами данных. Однако, чтобы использовать эти свойства, Вы должны знать, какие наборы символов и объединения являются доступными, как изменить значения по умолчанию, и как они воздействуют на поведение строковых операторов и функций.

10.2. Наборы символов и объединения в MySQL

Сервер MySQL может поддерживать много наборов символов. Чтобы вносить в список доступные наборы символов, используйте инструкцию SHOW CHARACTER SET. Ниже приведен кусок вывода этой команды:

mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+--------+
| Charset  | Description                 | Default collation   | Maxlen |
+----------+-----------------------------+---------------------+--------+
|     big5 | Big5 Traditional Chinese    | big5_chinese_ci     | 2      |
|     dec8 | DEC West European           | dec8_swedish_ci     | 1      |
|    cp850 | DOS West European           | cp850_general_ci    | 1      |
|      hp8 | HP West European            | hp8_english_ci      | 1      |
|    koi8r | KOI8-R Relcom Russian       | koi8r_general_ci    | 1      |
|   latin1 | cp1252 West European        | latin1_swedish_ci   | 1      |
|   latin2 | ISO 8859-2 Central European | latin2_general_ci   | 1      |
|     swe7 | 7bit Swedish                | swe7_swedish_ci     | 1      |
|    ascii | US ASCII                    | ascii_general_ci    | 1      |
|     ujis | EUC-JP Japanese             | ujis_japanese_ci    | 3      |
|     sjis | Shift-JIS Japanese          | sjis_japanese_ci    | 2      |
|   hebrew | ISO 8859-8 Hebrew           | hebrew_general_ci   | 1      |
|   tis620 | TIS620 Thai                 | tis620_thai_ci      | 1      |
|    euckr | EUC-KR Korean               | euckr_korean_ci     | 2      |
|    koi8u | KOI8-U Ukrainian            | koi8u_general_ci    | 1      |
|   gb2312 | GB2312 Simplified Chinese   | gb2312_chinese_ci   | 2      |
|    greek | ISO 8859-7 Greek            | greek_general_ci    | 1      |
|   cp1250 | Windows Central European    | cp1250_general_ci   | 1      |
|      gbk | GBK Simplified Chinese      | gbk_chinese_ci      | 2      |
|   latin5 | ISO 8859-9 Turkish          | latin5_turkish_ci   | 1      |
...

Любой заданный набор символов всегда имеет по крайней мере одно объединение, но может иметь и несколько объединений. Чтобы вносить в список объединения для набора символов, используйте инструкцию SHOW COLLATION. Например, чтобы увидеть объединения для набора символов latin1, используйте эту инструкцию, чтобы найти те имена объединения, которые начинаются с latin1:

mysql> SHOW COLLATION LIKE 'latin1%';
+--------------------+---------+----+---------+----------+---------+
| Collation          | Charset | Id | Default | Compiled | Sortlen |
+--------------------+---------+----+---------+----------+---------+
| latin1_german1_ci  | latin1  |  5 |         |          | 0       |
| latin1_swedish_ci  | latin1  |  8 | Yes     | Yes      | 1       |
| latin1_danish_ci   | latin1  | 15 |         |          | 0       |
| latin1_german2_ci  | latin1  | 31 |         | Yes      | 2       |
| latin1_bin         | latin1  | 47 |         | Yes      | 1       |
| latin1_general_ci  | latin1  | 48 |         |          | 0       |
| latin1_general_cs  | latin1  | 49 |         |          | 0       |
| latin1_spanish_ci  | latin1  | 94 |         |          | 0       |
+--------------------+---------+----+---------+----------+---------+

Объединения в latin1 имеют следующие значения:

Объединение Значение
latin1_german1_ciGerman DIN-1
latin1_swedish_ciSwedish/Finnish
latin1_danish_ciDanish/Norwegian
latin1_german2_ciGerman DIN-2
latin1_binBinary according to latin1 encoding
latin1_general_ci Multilingual (Western European)
latin1_general_csMultilingual (ISO Western European), case sensitive
latin1_spanish_ciModern Spanish

Объединения имеют эти общие характеристики:

10.3. Определение наборов символов и объединений

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

CHARACTER SET используется в предложениях, которые определяют набор символов. CHARSET может использоваться как синоним для CHARACTER SET.

10.3.1. Набор символов и объединение на стороне сервера

Сервер MySQL имеет набор символов и объединение сервера. Они могут быть установлены при запуске и изменены во время выполнения.

Первоначально, набор символов и объединение зависят от параметров, которые Вы используете, когда запускаете mysqld . Вы можете использовать --character-set-server для набора символов. Наряду с этим, Вы можете добавлять --collation-server для объединения. Если Вы не определяете набор символов, считается, что задано --character-set-server=latin1. Если Вы определяете только набор символов (например, latin1), но не задаете объединение, считается, что задано --character-set-server=latin1 --collation-server=latin1_swedish_ci, потому что latin1_swedish_ci заданное по умолчанию объединение для latin1. Следовательно, следующий три команды все имеют тот же самый эффект:

shell> mysqld
shell> mysqld --character-set-server=latin1
shell> mysqld --character-set-server=latin1 \
                 --collation-server=latin1_swedish_ci

Один способ изменят параметры настройки: перекомпиляция. Если Вы хотите изменять заданный по умолчанию набор символов сервера и объединение при формировании из исходных текстов, используйте: --with-charset и --with-collation в качестве параметров для configure. Например:

shell> ./configure --with-charset=latin1

Или:

shell> ./configure --with-charset=latin1 \
                      --with-collation=latin1_german1_ci

mysqld и скрипт configure проверяют, что комбинация объединений и наборов символов допустима. Если это не так, каждая из упомянутых программ отображает сообщение об ошибке и завершается.

Текущий набор символов и объединение сервера могут быть определены из значений переменных системы character_set_server и collation_server. Эти переменные могут быть изменены во время выполнения.

10.3.2. Набор символов и объединение базы данных

Каждая база данных имеет набор символов и объединение базы данных. Инструкции CREATE DATABASE и ALTER DATABASE имеет факультативные предложения для определения набора символов базы данных и объединения:

CREATE DATABASE db_name
       [[DEFAULT] CHARACTER SET charset_name]
       [[DEFAULT] COLLATE collation_name]

ALTER DATABASE db_name
      [[DEFAULT] CHARACTER SET charset_name]
      [[DEFAULT] COLLATE collation_name]

Ключевое слово SCHEMA может использоваться вместо DATABASE.

Все параметры базы данных сохранены в текстовом файле db.opt, который может быть найден в каталоге баз данных.

Предложения CHARACTER SET и COLLATE делают возможным создать базы данных с различными наборами символов и объединениями на том же самом сервере MySQL.

Пример:

CREATE DATABASE db_name CHARACTER SET latin1
       COLLATE latin1_swedish_ci;

MySQL выбирает набор символов и объединение базы данных следующим способом:

Набор символов базы данных и объединение используется как значения по умолчанию, если набор символов таблицы и объединение не определен в инструкции CREATE TABLE. Они не имеют никакой другой цели.

Набор символов и объединение для заданной по умолчанию базы данных может быть определено из значений переменных системы character_set_database и collation_database. Сервер устанавливает эти переменные всякий раз, когда заданная по умолчанию база данных изменяется. Если не имеется никакой заданной по умолчанию базы данных, переменные имеют то же самое значение, что и соответствующие переменные системы уровня сервера: character_set_server и collation_server.

10.3.3. Набор символов и объединение таблицы

Каждая таблица имеет набор символов таблицы и объединение. Инструкции CREATE TABLE и ALTER TABLE имеют факультативные предложения для определения набора символов таблицы и объединения:

CREATE TABLE tbl_name
             (column_list)
       [[DEFAULT] CHARACTER SET charset_name]
       [COLLATE collation_name]]
ALTER TABLE tbl_name
      [[DEFAULT] CHARACTER SET charset_name]
      [COLLATE collation_name]

Пример:

CREATE TABLE t1 ( ... ) CHARACTER SET latin1 COLLATE latin1_danish_ci;

MySQL выбирает набор символов таблицы и объединение следующим способом:

Набор символов таблицы и объединение используется как значения по умолчанию, если набор символов столбца и объединение не определен в индивидуальных определениях столбца. Набор символов и объединение таблицы представляют собой расширения MySQL, не имеется ничего такого в стандарте SQL.

10.3.4. Набор символов и объединение столбца

Каждый символьный столбец (то есть, столбец типа CHAR, VARCHAR или TEXT) имеет набор символов и объединение столбца. Синтаксис определения столбца имеет факультативные предложения для определения набора символов и объединения столбца:

col_name {CHAR | VARCHAR | TEXT}
(col_length)
[CHARACTER SET charset_name]
[COLLATE collation_name]

Пример:

CREATE TABLE Table1
       (column1 VARCHAR(5) CHARACTER SET latin1
       COLLATE latin1_german1_ci);

MySQL выбирает набор символов столбца и объединение следующим способом:

Предложения CHARACTER SET и COLLATE стандартны для SQL.

10.3.5. Набор символов и объединение символьных строковых литералов

Каждый символьный строковый литерал имеет набор символов и объединение.

Символьный строковый литерал может иметь факультативный набор символов и предложение COLLATE:

[_charset_name]'string'
[COLLATE collation_name]

Пример:

SELECT 'string';
SELECT _latin1'string';
SELECT _latin1'string' COLLATE latin1_danish_ci;

Для простой инструкции SELECT 'string', строка имеет набор символов и объединение, определенное переменными системы character_set_connection и collation_connection.

Выражение _charset_name формально названо introducer. Это сообщает синтаксическому анализатору, что строка предположительно соответствует набору символов X. Поскольку было много путаницы в прошлом, следует особо подчеркнуть, что introducer не вызывает никаких преобразований, это строго сигнал, который не изменяет значение строки. Introducer также допустим перед стандартным шестнадцатеричным литералом и числовой шестнадцатеричной литеральной записью (x'literal' и 0xnnnn)>.

Пример:

SELECT _latin1 x'AABBCC';
SELECT _latin1 0xAABBCC;

MySQL определяет набор символов литерала и объединение следующим способом:

Пример:

Набор символов и предложение COLLATE выполнены согласно стандарту SQL

introducer указывает набор символов для следующей строки, но не изменяет того, как синтаксический анализатор выполняет обработку Escape внутри строки. Escape всегда интерпретируются синтаксическим анализатором согласно набору символов, заданному в character_set_connection.

Следующие примеры показывают, что происходит обработка Escape, используя character_set_connection даже в присутствии introducer. Примеры используют SET NAMES (который изменяет character_set_connection) и отображает возникающие в результате строки, использующие HEX(), чтобы было видно точное строковое содержимое.

Пример 1:

mysql> SET NAMES latin1;
Query OK, 0 rows affected (0.01 sec)
mysql> SELECT HEX('├а\n'), HEX(_sjis'├а\n');
+-------------+------------------+
| HEX('├а\n') | HEX(_sjis'├а\n') |
+-------------+------------------+
|        E00A | E00A             |
+-------------+------------------+
1 row in set (0.00 sec)

Здесь ├а (шестнадцатеричное значение E0) сопровождается \n, управляющей последовательностью для новой строки. Управляющая последовательность интерпретируется, используя значение character_set_connection latin1, чтобы произвести литерал newline (новая строка, шестнадцатеричное значение 0A). Это случается даже для второй строки. То есть introducer _sjis не воздействует на обработку синтаксического анализатора Escape.

Пример 2:

mysql> SET NAMES sjis;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT HEX('├а\n'), HEX(_latin1'├а\n');
+-------------+--------------------+
| HEX('├а\n') | HEX(_latin1'├а\n') |
+-------------+--------------------+
|      E05C6E |             E05C6E |
+-------------+--------------------+
1 row in set (0.04 sec)

Здесь character_set_connection равен sjis, набор символов в котором последовательность ├а сопровождается \ (шестнадцатеричные значения 05 и 5C), допустимый многобайтовый символ. Следовательно, первые два байта строки интерпретируются как одиночный символ sjis, и \ не обрабатывается как символ ESC. Следующий n (шестнадцатеричное значение 6E) не интерпретируется как часть управляющей последовательности. Таким образом, introducer _latin1 не воздействует на обработку Escape.

10.3.6. Национальный набор символов

Стандарт SQL определяет NCHAR или NATIONAL CHAR как способ указать, что столбец CHAR должен использовать некоторый предопределенный набор символов. MySQL 5.1 использует utf8 как этот предопределенный набор символов. Например, эти объявления типа данных эквивалентны:

CHAR(10) CHARACTER SET utf8
NATIONAL CHARACTER(10)
NCHAR(10)

Эти тоже взаимозаменяемы:

VARCHAR(10) CHARACTER SET utf8
NATIONAL VARCHAR(10)
NCHAR VARCHAR(10)
NATIONAL CHARACTER VARYING(10)
NATIONAL CHAR VARYING(10)

Вы можете использовать N'literal', чтобы создать строку в национальном наборе символов. Эти две инструкции эквивалентны:

SELECT N'some text';
SELECT _utf8'some text';

10.3.7. Примеры назначения набора символов и объединения

Следующие примеры показывают, как MySQL определяет заданные по умолчанию набор символов и объединение.

Пример 1: определение таблицы и столбца

CREATE TABLE t1 (c1 CHAR(10) CHARACTER SET latin1 COLLATE latin1_german1_ci)
       DEFAULT CHARACTER SET latin2
       COLLATE latin2_bin;

Здесь мы имеем столбец с набором символов latin1 и объединением latin1_german1_ci. Определение явно, так что это просто. Обратите внимание, что не имеется никакой проблемы с сохранением столбца latin1 в таблице latin2.

Пример 2: определение таблицы и столбца

CREATE TABLE t1 (c1 CHAR(10) CHARACTER SET latin1)
       DEFAULT CHARACTER SET latin1
       COLLATE latin1_danish_ci;

На сей раз мы имеем столбец с набором символов latin1 и заданным по умолчанию объединением. Хотя это могло бы показаться естественным, заданное по умолчанию объединение не принимается из уровня таблицы. Вместо этого, поскольку заданное по умолчанию объединение для latin1 обязательно latin1_swedish_ci, столбец c1 имеет объединение latin1_swedish_ci (не latin1_danish_ci).

Пример 3: определение таблицы и столбца

CREATE TABLE t1 (c1 CHAR(10))
       DEFAULT CHARACTER SET latin1
       COLLATE latin1_danish_ci;

Мы имеем столбец с заданными по умолчанию набором символов и объединением. В этой ситуации MySQL проверяет уровень таблицы, чтобы определить набор символов столбца и объединение. Следовательно, набор символов для столбца c1 latin1 и объединение latin1_danish_ci.

Пример 4: определение базы данных, таблицы и столбца

CREATE DATABASE d1 DEFAULT CHARACTER SET latin2
       COLLATE latin2_czech_ci; USE d1;
CREATE TABLE t1 (c1 CHAR(10));

Мы создаем столбец без того, чтобы определить набор символов и объединение. Мы также не определяем набор символов и объединение в уровне таблицы. В этой ситуации MySQL проверяет уровень базы данных, чтобы определить параметры настройки таблицы, которые с этого времени станут параметрами настройки столбца. Следовательно, набор символов для столбца c1 latin2 и объединение latin2_czech_ci.

10.3.8. Совместимость с другими СУБД

Для совместимости с MaxDB эти две инструкции те же самые:

CREATE TABLE t1 (f1 CHAR(N) UNICODE);
CREATE TABLE t1 (f1 CHAR(N)
       CHARACTER SET ucs2);

10.4. Наборы символов и объединения подключения

Несколько переменных системы для наборов символов и объединений касаются взаимодействия пользователя с сервером. Некоторые из них были упомянуты в более ранних разделах:

Дополнительный набор символов и объединения переменные системы включаются в трафике обработки для подключения. Каждый пользователь имеет связанные с подключением переменные системы набора символов и объединения.

Когда Вы соединяетесь с сервером, клиент посылает инструкции SQL. Сервер посылает ответы, типа наборов результатов, обратно пользователю. Это ведет к нескольким вопросам относительно набора символов и обработки объединения для подключений пользователя, каждому из которых можно отвечать в терминах переменных системы:

Вы можете подстраивать параметры настройки для этих переменных или зависеть от значений по умолчанию (тогда Вы можете пропустить остальную часть этого раздела).

Имеются две инструкции, которые воздействуют на наборы символов подключения:

SET NAMES 'charset_name'
SET CHARACTER SET charset_name

SET NAMES указывает то, какой набор символов применяет пользователь, чтобы послать инструкции SQL на сервер. Таким образом, SET NAMES 'cp1251' сообщает, что будущие входящие сообщения от этого пользователя находятся в наборе символов cp1251. Это также определяет набор символов, который сервер должен использовать для посылки результатов обратно пользователю. Например, это указывает то, какой набор символов использовать для значений столбца, если Вы используете инструкцию SELECT.

Инструкция SET NAMES 'x' эквивалентна этим трем инструкциям:

SET character_set_client = x;
SET character_set_results = x;
SET character_set_connection = x;

Установка character_set_connection в x также устанавливает collation_connection к заданному по умолчанию объединению для x. Чтобы определять специфическое объединение для наборов символов, используйте факультативное предложение COLLATE:

SET NAMES 'charset_name'
    COLLATE 'collation_name'

SET CHARACTER SET подобен SET NAMES, но устанавливает character_set_connection и collation_connection в character_set_database и collation_database. Инструкция SET CHARACTER SET x эквивалентна этим трем инструкциям:

SET character_set_client = x;
SET character_set_results = x;
SET collation_connection = @@collation_database;

Установка collation_connection также устанавливает character_set_connection к набору символов, связанному с объединением (эквивалент выполнения SET character_set_connection = @@character_set_database).

Когда пользователь соединяется, он посылает серверу имя набора символов, который требуется использовать. Сервер использует имя, чтобы установить переменные системы character_set_client, character_set_results и character_set_connection. В действительности сервер выполняет операцию SET NAMES, использующую имя набора символов.

С клиентом mysql нет необходимости выполнять SET NAMES каждый раз при запуске, если Вы хотите использовать набор символов, отличный от значения по умолчанию. Вы можете добавить опцию --default-character-set в операторной строке mysql или в Вашем файле опций. Например, следующий файл опций, устанавливает изменения трех переменных наборов символов к koi8r каждый раз, когда Вы вызываете mysql:

[mysql]
default-character-set=koi8r

Если Вы используете клиент mysql с поддержкой реконнекта (что вообще-то не рекомендуется), предпочтительно использовать команду charset, а не SET NAMES. Например:

mysql> charset utf8
Charset changed

Команда charset выдает инструкцию SET NAMES, а также изменяет заданный по умолчанию набор символов, который используется, если mysql повторно соединяется после того, как подключение прервалось.

Пример: Предположите, что column1 определен как CHAR(5) CHARACTER SET latin2. Если Вы не говорите SET NAMES или SET CHARACTER SET, то для then for SELECT column1 FROM t сервер посылает обратно все значения column1, использующий набор символов, который пользователь определил, когда соединялся. С другой стороны, если Вы говорите SET NAMES 'latin1' или SET CHARACTER SET latin1 перед выдачей инструкции SELECT, сервер преобразовывает значения latin2 в latin1 только перед посылкой результатов обратно. Преобразование может быть с потерями, если имеются символы, которые не представлены в обоих наборах символов.

Если Вы не хотите, чтобы сервер выполнил любое преобразование наборов результатов, установите character_set_results в NULL:

SET character_set_results = NULL;

Обратите внимание: в настоящее время UCS-2 не может использоваться как набор символов пользователя, это означает, что SET NAMES 'ucs2' не работает.

Чтобы видеть значения переменных системы набора символов и объединения, которые обращаются к Вашему подключению, используйте эти инструкции:

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

10.5. Проблемы объединения

Следующие разделы излагают различные аспекты объединений набора символов.

10.5.1. Использование COLLATE в SQL-инструкциях

С предложением COLLATE Вы можете отменять любое заданное по умолчанию объединение для сравнения. COLLATE может использоваться в различных частях инструкций SQL. Имеются некоторые примеры:

10.5.2. Старшинство предложения COLLATE

Предложение COLLATE имеет высокое старшинство (выше, чем ||), так следующие два выражения эквивалентны:

x || y COLLATE z
x || (y COLLATE z)

10.5.3. Оператор BINARY

Оператор BINARY приводит строку после него к двоичной строке. Это простой способ вынудить сравнение быть выполненным байт в байт, а не символ в символ. BINARY также заставляет конечные пробелы быть значительными.

mysql> SELECT 'a' = 'A';
    -> 1
mysql> SELECT BINARY 'a' = 'A';
    -> 0
mysql> SELECT 'a' = 'a ';
    -> 1
mysql> SELECT BINARY 'a' = 'a ';
    -> 0

BINARY str сокращение для CAST(str AS BINARY).

Атрибут BINARY на символьных определениях столбца имеет различный эффект. Символьному столбцу, определенному с атрибутом BINARY, назначено двоичное объединение набора символов столбца. Каждый набор символов имеет двоичное объединение. Например, двоичное объединение для набора символов latin1: latin1_bin, так что, если набор символов по умолчанию таблицы latin1, эти два столбца определены эквивалентно:

CHAR(10) BINARY
CHAR(10) CHARACTER SET latin1 COLLATE latin1_bin

Эффект BINARY как атрибута столбца отличается от эффекта до MySQL 4.1. Прежде BINARY помечал столбец, который обрабатывался как двоичная строка, то есть строка байтов, которая не имеет никакого набора символов или объединения, что отличается от не двоичной символьной строки, которая имеет двоичное объединение. Для обоих типов строк сравнения основаны на числовых значениях строкового модуля, но для не двоичных строк, модулем является символ, и некоторые наборы символов позволяют многобайтовые символы.

Использование CHARACTER SET binary на определении столбца CHAR, VARCHAR или TEXT заставляет столбец обрабатываться как двоичный тип данных. Например, следующие пары определений эквивалентны:

CHAR(10) CHARACTER SET binary
BINARY(10)
VARCHAR(10) CHARACTER SET binary
VARBINARY(10)
TEXT CHARACTER SET binary
BLOB

10.5.4. Некоторые специальные случаи, где определение объединения сложно

В большинстве инструкций, очевидно, какое объединение MySQL использует, чтобы решить операцию сравнения. Например, в следующих случаях, должно быть четко ясно, что объединением будет объединение столбца x:

SELECT x FROM T ORDER BY x;
SELECT x FROM T WHERE x = x;
SELECT DISTINCT x FROM T;

Однако, когда включаются многократные операнды, может иметься неоднозначность. Например:

SELECT x FROM T WHERE x = 'Y';

Это должно использовать объединение из столбца x или от литерала строки 'Y'?

Стандарт SQL решает такие вопросы, применяя правило coercibility. В основном это означает: раз x и 'Y' имеют объединения, которое объединение имеет приоритет? Это может быть трудно решить, но следующие правила покрывают большинство ситуаций:

Предшествующие значения coercibility текущие для MySQL 5.1.

Эти правила решают неоднозначности следующим способом:

Пример:

column1 = 'A' Использует объединение column1
column1 = 'A' COLLATE x Использует объединение 'A' COLLATE x
column1 COLLATE x = 'A' COLLATE y Ошибка

Функция COERCIBILITY() может использоваться, чтобы определить coercibility строкового выражения:

mysql> SELECT COERCIBILITY('A' COLLATE latin1_swedish_ci);
    -> 0
mysql> SELECT COERCIBILITY(VERSION());
    -> 3
mysql> SELECT COERCIBILITY('A');
    -> 4

10.5.5. Объединения должны быть для правильного набора символов

Каждый набор символов имеет одно или большее количество объединений, но каждое объединение связано с одним и только одним набором символов. Следовательно, следующая инструкция вызывает сообщение об ошибке, потому что объединение latin2_bin не допустимо с набором символов latin1:

mysql> SELECT _latin1 'x' COLLATE latin2_bin;
ERROR 1253 (42000): COLLATION 'latin2_bin' is not valid
for CHARACTER SET 'latin1'

10.5.6. Пример эффекта объединения

Предположите, что столбец X в таблице T имеет эти значения столбца latin1:

Muffler
M├╝ller
MX Systems
MySQL

Предположите также, что значения столбца получены, используя следующую инструкцию:

SELECT X FROM T ORDER BY X COLLATE collation_name;

Следующая таблица показывает возникающий в результате порядок значений, если мы используем ORDER BY с различными объединениями:

latin1_swedish_ci latin1_german1_cilatin1_german2_ci
MufflerMufflerM├╝ller
MX SystemsM├╝llerMuffler
M├╝llerMX SystemsMX Systems
MySQLMySQLMySQL

Символ, который вызывает различные порядки сортировки в этом примере: U с двумя точками сверху, который в Германии известен как U-umlaut.

10.6. Операции, на которые воздействует поддержка набора символов

Этот раздел описывает операции, которые берут во внимание информацию о наборе символов.

10.6.1. Строки результата

MySQL имеет много операторов и функций, которые возвращают строку. Этот раздел отвечает на вопрос: каков набор символов и объединение у такой строки?

Для простых функций, которые берут строку ввода и возвращают строковый результат как вывод, набор символов и объединение вывода такие же, как таковые у входного значения. Например, UPPER(X) возвращает строку, чья символьная строка и объединение являются такими же, как X. Это относится к INSTR(), LCASE(), LOWER(), LTRIM(), MID(), REPEAT(), REPLACE(), REVERSE(), RIGHT(), RPAD(), RTRIM(), SOUNDEX(), SUBSTRING(), TRIM(), UCASE() и UPPER().

Обратите внимание: функция REPLACE(), в отличие от всех других функций, всегда игнорирует объединение строкового ввода и выполняет чувствительное к регистру сравнение.

Если строковый ввод или функциональный результат является двоичной строкой, она не имеет никакого набора символов или объединения. Это может быть проверено, используя функции CHARSET() и COLLATION(), которые вернут binary, чтобы указать, что их параметр двоичная строка:

mysql> SELECT CHARSET(BINARY 'a'), COLLATION(BINARY 'a');
+---------------------+-----------------------+
| CHARSET(BINARY 'a') | COLLATION(BINARY 'a') |
+---------------------+-----------------------+
|              binary |                binary |
+---------------------+-----------------------+

Для операций, которые объединяют многостроковые вводы и возвращают одиночный строковый вывод, правила соединения частей стандарта SQL дают определение объединения результата:

Например, с CASE ... WHEN a THEN b WHEN b THEN c COLLATE X END возникающее в результате объединение X. То же самое для UNION, ||, CONCAT(), ELT(), GREATEST(), IF() и LEAST().

Для операций, которые преобразовываются в символьные данные, набор символов и объединение строк результата операции определены переменными системы character_set_connection и collation_connection. Это применяется только для CAST(), CONV(), FORMAT(), HEX() и SPACE().

Если Вы не уверены относительно набора символов или объединения результата, возвращенного строковой функцией, Вы можете использовать функцию CHARSET() или COLLATE(), чтобы выяснить:

mysql> SELECT USER(), CHARSET(USER()), COLLATION(USER());
+----------------+-----------------+-------------------+
| USER()         | CHARSET(USER()) | COLLATION(USER()) |
+----------------+-----------------+-------------------+
| test@localhost | utf8            | utf8_general_ci   |
+----------------+-----------------+-------------------+

10.6.2. CONVERT() и CAST()

CONVERT() обеспечивает способ преобразовать данные между различными наборами символов. Синтаксис:

CONVERT(expr USING transcoding_name)

В MySQL имена перекодировки такие же, как соответствующие имена наборов символов.

Примеры:

SELECT CONVERT(_latin1'M├╝ller' USING utf8);
INSERT INTO utf8table (utf8column)
SELECT CONVERT(latin1field USING utf8) FROM latin1table;

CONVERT(... USING ...) выполнено согласно стандарту SQL.

Вы можете также использовать CAST(), чтобы преобразовать строку в иной набор символов. Синтаксис:

CAST(character_string AS
     character_data_type
     CHARACTER SET charset_name)

Пример:

SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8);

Если Вы используете CAST() без того, чтобы определить CHARACTER SET, возникающие в результате набор символов и объединение определены переменными системы character_set_connection и collation_connection. Если Вы используете CAST() с CHARACTER SET X, возникающие в результате набор символов и объединение X и заданное по умолчанию объединение для X.

Вы не можете использовать предложение COLLATE внутри CAST(), но Вы можете использовать это снаружи. То есть CAST(... COLLATE ...) запрещено, но CAST(...) COLLATE ... допустимо.

Пример:

SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin;

10.6.3. Инструкции SHOW и INFORMATION_SCHEMA

Несколько инструкций SHOW обеспечивают дополнительную информацию о наборе символов. Они включают SHOW CHARACTER SET, SHOW COLLATION, SHOW CREATE DATABASE, SHOW CREATE TABLE и SHOW COLUMNS. Эти инструкции описаны здесь кратко.

INFORMATION_SCHEMA имеет несколько таблиц, которые содержат информацию, подобную отображаемой инструкциями SHOW. Например, таблицы CHARACTER_SETS и COLLATIONS содержат информацию, отображаемую SHOW CHARACTER SET и SHOW COLLATION.

Команда SHOW CHARACTER SET показывает все доступные наборы символов. Требуется факультативное предложение LIKE, которое указывает, которым именам набора символов соответствовать. Например:

mysql> SHOW CHARACTER SET LIKE 'latin%';
+---------+-----------------------------+-------------------+--------+
| Charset | Description                 | Default collation | Maxlen |
+---------+-----------------------------+-------------------+--------+
| latin1  | cp1252 West European        | latin1_swedish_ci | 1      |
| latin2  | ISO 8859-2 Central European | latin2_general_ci | 1      |
| latin5  | ISO 8859-9 Turkish          | latin5_turkish_ci | 1      |
| latin7  | ISO 8859-13 Baltic          | latin7_general_ci | 1      |
+---------+-----------------------------+-------------------+--------+

Вывод SHOW COLLATION включает все доступные наборы символов. Требуется факультативное предложение LIKE, которое указывает, которым именам объединения соответствовать. Например:

mysql> SHOW COLLATION LIKE 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation         | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1  |  5 |         |          | 0       |
| latin1_swedish_ci | latin1  |  8 | Yes     | Yes      | 0       |
| latin1_danish_ci  | latin1  | 15 |         |          | 0       |
| latin1_german2_ci | latin1  | 31 |         | Yes      | 2       |
| latin1_bin        | latin1  | 47 |         | Yes      | 0       |
| latin1_general_ci | latin1  | 48 |         |          | 0       |
| latin1_general_cs | latin1  | 49 |         |          | 0       |
| latin1_spanish_ci | latin1  | 94 |         |          | 0       |
+-------------------+---------+----+---------+----------+---------+

SHOW CREATE DATABASE отображает инструкцию CREATE DATABASE, которая создала эту базу данных:

mysql> SHOW CREATE DATABASE test;
+----------+-----------------------------------------+
| Database | Create Database                         |
+----------+-----------------------------------------+
| test     | CREATE DATABASE `test` /*!40100 DEFAULT |
|          | CHARACTER SET latin1 */                 |
+----------+-----------------------------------------+

Если никакое предложение COLLATE не показывается, заданное по умолчанию объединение для набора символов применяется.

SHOW CREATE TABLE подобна, но отображает инструкцию CREATE TABLE, чтобы создать данную таблицу. Определения столбца указывают любые спецификации набора символов, и параметры таблицы включают информацию набора символов.

Инструкция SHOW COLUMNS отображает объединения столбцов таблицы когда вызывается как SHOW FULL COLUMNS. Столбцы с типами данных CHAR, VARCHAR или TEXT имеют объединения. Числовые и другие не-символьные типы не имеют никакого объединения (обозначены NULL как значение Collation). Например:

mysql> SHOW FULL COLUMNS FROM person\G
*************************** 1. row ***************************
Field: id
Type: smallint(5) unsigned
Collation: NULL
Null: NO
Key: PRI
Default: NULL
Extra: auto_increment
Privileges: select, insert, update, references
Comment:
*************************** 2. row ***************************
Field: name
Type: char(60)
Collation: latin1_swedish_ci
Null: NO
Key:
Default:
Extra:
Privileges: select, insert, update, references
Comment:

Набор символов не отображается, но подразумевается именем объединения.

10.7. Поддержка Unicode

MySQL 5.1 поддерживает два набора символов для сохранения данных Unicode:

В UCS-2 (двоичное представление Unicode) каждый символ представляется двухбайтным Unicode-кодом со старшим байтом сначала. Например: LATIN CAPITAL LETTER A имеет код 0x0041, и это сохранено как двухбайтовая последовательность 0x00 0x41. CYRILLIC SMALL LETTER YERU (Unicode 0x044B) сохранена как двухбайтовая последовательность 0x04 0x4B. Для получения символов Unicode и их кодов, пожалуйста, обратитесь к Unicode Home Page (http://www.unicode.org).

В настоящее время UCS-2 не может использоваться как набор символов пользователя, это означает, что SET NAMES 'ucs2' не работает.

UTF-8 (трансформируемое представление Unicode) представляет собой альтернативный способ сохранить Unicode данные. Это выполнено согласно RFC 3629. Идея относительно UTF-8 состоит в том, что различные символы Unicode, используя последовательности байтов различных длин:

RFC 3629 описывает последовательности кодирования, которые берут от одного до четырех байтов. В настоящее время MySQL-поддержка для UTF-8 не включает последовательности с четырьмя байтами. Старый стандарт для кодирования UTF-8 задан RFC 2279 и описывает UTF-8-последовательности, которые берут от одного до шести байтов. RFC 3629 объявляет RFC 2279 устаревшим, по этой причине последовательности с пятью и шестью байтами больше не используются.

Совет: чтобы сохранять пробел а UTF-8, используйте VARCHAR вместо CHAR. Иначе MySQL должен резервировать по три байта для каждого символа в столбце CHAR CHARACTER SET utf8, потому что это максимальная возможная длина. Например, MySQL должен резервировать 30 байтов для столбца CHAR(10) CHARACTER SET utf8.

10.8. UTF-8 для метаданных

Метаданные представляют собой такие данные, которые описывают базу данных в противоположность данным, являющимся содержанием базы данных. Таким образом, имена столбцов, базы данных, пользователей, версия и большинство строк-результатов SHOW как раз и являются именно метаданными. Это также истинно для содержания таблиц в INFORMATION_SCHEMA, потому что те таблицы по определению содержат информацию относительно объектов базы данных.

Представление метаданных должно удовлетворять эти требованиям:

Чтобы удовлетворять обоим требованиям, MySQL сохраняет метаданные в наборе символов Unicode, а именно в UTF-8. Это не вызывает никаких сбоев, если Вы никогда не используете не латинские или символы с диакритическим знаком. Но если Вы это делаете, Вы должны знать, что метаданные находятся в UTF-8.

Требования метаданных означают, что возвращаемые значения функций USER(), CURRENT_USER(), SESSION_USER(), SYSTEM_USER(), DATABASE() и VERSION() имеют по умолчанию набор символов UTF-8.

Сервер устанавливает переменную системы character_set_system к имени набора символов метаданных:

mysql> SHOW VARIABLES LIKE 'character_set_system';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| character_set_system | utf8  |
+----------------------+-------+

Хранение метаданных, использующих Unicode, не означает, что сервер возвращает заголовки столбцов и результатов функции DESCRIBE в наборе символов character_set_system по умолчанию. Когда Вы используете SELECT column1 FROM t, имя column1 непосредственно возвращено в наборе символов, определенном значением переменной системы character_set_results, которая имеет значение по умолчанию latin1. Если Вы хотите, чтобы сервер передал результаты метаданных в ином наборе символов, используйте инструкцию SET NAMES, чтобы выполнять преобразование набора символов. SET NAMES устанавливает character_set_results и другие связанные переменные системы. В качестве альтернативы программа пользователя может выполнять преобразование после получения результата с сервера. Это более эффективно для пользователя, но эта опция не всегда доступна для всей клиентуры.

Если character_set_results установлен в NULL, никакое преобразование не выполняется и метаданные возвращаются, используя первоначальный набор символов (набор, обозначенный character_set_system).

Сообщения об ошибках, возвращенные сервером, преобразованы в набор символов пользователя автоматически, как в случае с метаданными.

Если Вы используете (например) функцию USER() для сравнения или назначения внутри одиночной инструкции, можете не волноваться. MySQL выполняет автоматическое преобразование для Вас.

SELECT * FROM Table1 WHERE USER() = latin1_column;

Это работает потому, что содержание latin1_column автоматически преобразовано в UTF-8 перед сравнением.

INSERT INTO Table1 (latin1_column) SELECT USER();

Это работает потому, что содержание USER() автоматически преобразовано в latin1 перед назначением. Автоматическое преобразование полностью все же не выполнено, но должно работать правильно в более поздней версии.

Хотя автоматическое преобразование не в SQL стандарте, документ SQL-стандарта говорит, что каждый набор символов (в терминах обеспечиваемых символов) подмножество Unicode. Поэтому объединение для Unicode может применяться для сравнения с не-Unicode строками.

10.9. Преобразование набора символов столбца

Чтобы преобразовывать двоичный или не двоичный строковый столбец, чтобы использовать специфический набор символов, примените ALTER TABLE. Для успешного преобразования одно из следующих условий должно примениться:

Предположите, что таблица t имеет двоичный столбец col1, определенный как BINARY(50). При условии, что информация в столбце закодирована, используя одиночный набор символов, Вы можете преобразовывать это в не двоичный столбец, который имеет нужный набор символов. Например, если col1 содержит двоичные символы представления данных в греческом наборе символов (greek), Вы можете преобразовывать это следующим образом:

ALTER TABLE t MODIFY col1 CHAR(50) CHARACTER SET greek;

Предположите, что таблица t имеет не двоичный столбец col1, определенный как CHAR(50) CHARACTER SET latin1 , но Вы хотите преобразовывать это, чтобы использовать utf8 так, чтобы Вы могли сохранять значения из многих языков. Следующая инструкция выполняет это:

ALTER TABLE t MODIFY col1 CHAR(50) CHARACTER SET utf8;

Преобразование может быть с потерями, если столбец содержит символы, которые не содержатся в обоих наборах символов.

Специальный случай происходит, если Вы имеете старые таблицы из MySQL 4.0 или ранее, где не двоичный столбец содержит значения, которые фактически закодированы в наборе символов, отличном от заданного по умолчанию набора символов сервера. Например, прикладная программа могла бы сохранить значения sjis в столбце даже при том, что заданный по умолчанию набор символов MySQL latin1. Возможно преобразовать столбец, чтобы использовать соответствующий набор символов, но дополнительный шаг требуется. Предположите, что заданный по умолчанию набор символов сервера был latin1, а col1 определен как CHAR(50), но содержит значения в sjis. Первый шаг должен преобразовать столбец в двоичный тип данных, который удаляет существующую информацию набора символов без того, чтобы выполнить любое символьное преобразование:

ALTER TABLE t MODIFY col1 BINARY(50);

Следующий шаг должен преобразовать столбец в не двоичный тип данных с соответствующим набором символов:

ALTER TABLE t MODIFY col1 CHAR(50) CHARACTER SET sjis;

Эта процедура требует, чтобы таблица не изменилась с инструкциями типа INSERT или UPDATE после обновления до MySQL 4.1 или позже. В этом случае MySQL сохранил бы новые значения в столбце, использующем latin1, и столбец будет содержать смесь значений sjis и latin1, а значит не может быть преобразован правильно.

Если Вы определили атрибуты при создании столбца первоначально, Вы должны также определить их, при изменении таблицы с помощью ALTER TABLE. Например, если Вы определили NOT NULL и явное значение DEFAULT, Вы должны также обеспечить их в инструкции ALTER TABLE. Иначе возникающее в результате определение столбца не будет включать эти атрибуты.

10.10. Наборы символов и объединения, которые поддерживает MySQL

MySQL поддерживает свыше 70 объединений для более 30 наборов символов. Этот раздел указывает, которые наборы символов MySQL поддерживает. Имеется один подраздел для каждой группы связанных наборов символов. Для каждого набора символов, перечислены допустимые объединения.

Вы можете всегда вносить в список доступные наборы символов и их заданные по умолчанию объединения инструкцией SHOW CHARACTER SET:

mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+
| Charset  | Description                 | Default collation   |
+----------+-----------------------------+---------------------+
| big5     | Big5 Traditional Chinese    | big5_chinese_ci     |
| dec8     | DEC West European           | dec8_swedish_ci     |
| cp850    | DOS West European           | cp850_general_ci    |
| hp8      | HP West European            | hp8_english_ci      |
| koi8r    | KOI8-R Relcom Russian       | koi8r_general_ci    |
| latin1   | cp1252 West European        | latin1_swedish_ci   |
| latin2   | ISO 8859-2 Central European | latin2_general_ci   |
| swe7     | 7bit Swedish                | swe7_swedish_ci     |
| ascii    | US ASCII                    | ascii_general_ci    |
| ujis     | EUC-JP Japanese             | ujis_japanese_ci    |
| sjis     | Shift-JIS Japanese          | sjis_japanese_ci    |
| hebrew   | ISO 8859-8 Hebrew           | hebrew_general_ci   |
| tis620   | TIS620 Thai                 | tis620_thai_ci      |
| euckr    | EUC-KR Korean               | euckr_korean_ci     |
| koi8u    | KOI8-U Ukrainian            | koi8u_general_ci    |
| gb2312   | GB2312 Simplified Chinese   | gb2312_chinese_ci   |
| greek    | ISO 8859-7 Greek            | greek_general_ci    |
| cp1250   | Windows Central European    | cp1250_general_ci   |
| gbk      | GBK Simplified Chinese      | gbk_chinese_ci      |
| latin5   | ISO 8859-9 Turkish          | latin5_turkish_ci   |
| armscii8 | ARMSCII-8 Armenian          | armscii8_general_ci |
| utf8     | UTF-8 Unicode               | utf8_general_ci     |
| ucs2     | UCS-2 Unicode               | ucs2_general_ci     |
| cp866    | DOS Russian                 | cp866_general_ci    |
| keybcs2  | DOS Kamenicky Czech-Slovak  | keybcs2_general_ci  |
| macce    | Mac Central European        | macce_general_ci    |
| macroman | Mac West European           | macroman_general_ci |
| cp852    | DOS Central European        | cp852_general_ci    |
| latin7   | ISO 8859-13 Baltic          | latin7_general_ci   |
| cp1251   | Windows Cyrillic            | cp1251_general_ci   |
| cp1256   | Windows Arabic              | cp1256_general_ci   |
| cp1257   | Windows Baltic              | cp1257_general_ci   |
| binary   | Binary pseudo charset       | binary              |
| geostd8  | GEOSTD8 Georgian            | geostd8_general_ci  |
| cp932    | SJIS for Windows Japanese   | cp932_japanese_ci   |
| eucjpms  | UJIS for Windows Japanese   | eucjpms_japanese_ci |
+----------+-----------------------------+---------------------+

10.10.1. Наборы символов Unicode

MySQL имеет два набора символов Unicode. Вы можете сохранять текст приблизительно для 650 языков, используя эти наборы символов.

Обратите внимание, что в объединениях ucs2_roman_ci и utf8_roman_ci I и J считаются эквивалентными, равно как и пара U и V.

Объединения ucs2_hungarian_ci и utf8_hungarian_ci были добавлены в MySQL 5.1.5.

MySQL осуществляет объединение utf8_unicode_ci согласно Unicode Collation Algorithm (UCA), описанному на http://www.unicode.org/reports/tr10/. Объединение использует version-4.0.0 UCA weight keys: http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt. Следующее обсуждение использует utf8_unicode_ci, но это также верно и для ucs2_unicode_ci.

В настоящее время объединение utf8_unicode_ci имеет только частичную поддержку для Unicode Collation Algorithm. Некоторые символы все же не обеспечиваются. Также полностью не обеспечивается объединение меток. Это воздействует прежде всего на вьетнамский и некоторые малораспространенные языки в России, типа Udmurt, Tatar, Bashkir и Mari.

Старшее свойство в utf8_unicode_ci: это поддерживает расширения, то есть когда один символ сравнивается как равный комбинациям других символов. Например, в немецком и некоторых других языках ├Я равен ss.

utf8_general_ci объединение, которое не поддерживает расширения. Это может делать только взаимно-однозначные сравнения между символами. Это означает, что сравнения для объединения utf8_general_ci быстрее, но немного менее правильные, чем сравнения для utf8_unicode_ci.

Например, следующие равенства верны в utf8_general_ci и в utf8_unicode_ci:

├Д = A
├Ц = O
├Ь = U

Различие между объединениями: это является истинным для utf8_general_ci:

├Я = s

В то время, как это истинно для utf8_unicode_ci:

├Я = ss

MySQL осуществляет специфические для языка объединения для набора символов utf8 только, если упорядочение с utf8_unicode_ci не работает хорошо для языка. Например, utf8_unicode_ci работает прекрасно для German и French, а значит нет никакой потребности создавать специальные объединения utf8 для этих двух языков.

utf8_general_ci также удовлетворителен для German и French за исключением того, что ├Я равно s, но ss. Если это приемлемо для вашей прикладной программы, то применяйте utf8_general_ci, потому что это быстрее. Иначе, используйте utf8_unicode_ci, потому что это более точно.

utf8_swedish_ci, подобно другим специфическим для языка объединениям utf8, получен из utf8_unicode_ci с дополнительными правилами языка. Например, в Swedish следующие связи хранения, которые неприменимы для German или French:

├Ь = Y < ├Ц

Объединения utf8_spanish_ci и utf8_spanish2_ci соответствуют современному и традиционному испанскому, соответственно. В обоих объединениях ├▒ (n-tilde) отдельный символ между n и o. Кроме того, для традиионного испанского ch отдельный символ между c и d, а ll отдельный символ между l и m

10.10.2. Западноевропейские наборы символов

Западноевропейские наборы символов покрывают большинство западноевропейских языков, типа French, Spanish, Catalan, Basque, Portuguese, Italian, Albanian, Dutch, German, Danish, Swedish, Norwegian, Finnish, Faroese, Icelandic, Irish, Scottish и English.

10.10.3. Центральноевропейские наборы символов

MySQL обеспечивает поддержку для наборов символов, используемых в Czech Republic, Slovakia, Hungary, Romania, Slovenia, Croatia и Poland.

10.10.4. Южноевропейские и ближневосточные наборы символов

Южныоевропейские и ближневосточные наборы символов, обеспечиваемые MySQL, включают Armenian, Arabic, Georgian, Greek, Hebrew и Turkish.

10.10.5. Балтийские наборы символов

Балтийские наборы символов охватывают Estonian, Latvian и Lithuanian.

10.10.6. Наборы символов кириллицы

Наборы символов и объединения кириллицы для использования с Belarusian, Bulgarian, Russian и Ukrainian.

10.10.7. Азиатские наборы символов

Азиатские наборы символов, которые поддерживает пакет, включают Chinese, Japanese, Korean и Thai. Они могут быть усложнены. Например, китайские наборы должны учесть тысячи различных символов.

10.10.7.1. Набор символов cp932

А на кой вообще нужен cp932?

В MySQL набор символов sjis соответствует Shift_JIS определенному IANA, который поддерживает символы JIS X0201 и JIS X0208 (см. http://www.iana.org/assignments/character-sets).

Однако, значение SHIFT JIS как описательный термин стало очень неопределенным, и это часто включает расширения Shift_JIS, которые определены различными поставщиками. Короче, больше стандартов, хороших и разных!

Например, SHIFT JIS, использованный в Japanese Windows, представляет расширение Shift_JIS от Microsoft, и его точное название Microsoft Windows Codepage: 932 или cp932. В дополнение к символам, обеспечиваемым Shift_JIS, cp932 поддерживает символы расширения типа специальных и изюранных символов NEC и расширенных символов IBM.

Много японских пользователей испытали проблемы при использовании этих символов расширения. Эта проблема складывается из следующих факторов:

Набор символов MySQL cp932 разработан, чтобы решить эти проблемы.

Поскольку MySQL поддерживает преобразование набора символов, важно отделить IANA Shift_JIS от cp932: это два различных набора символов, потому что они обеспечивают разные правила преобразования.

А в чем разница между cp932 и sjis?

Набор символов cp932 отличается от sjis следующим:

Для некоторых символов, преобразование в и из ucs2 отлично для sjis и cp932. Следующие таблицы иллюстрируют эти различия.

Преобразование в ucs2:

sjis /cp932Значение sjis -> ucs2 преобразование cp932 ->ucs2 преобразование
5C005C005C
7E007E007E
815C20152015
815F005CFF3C
8160301CFF5E
816120162225
817C2212FF0D
819100A2FFE0
819200A3FFE1
81CA00ACFFE2

Преобразование из ucs2:

ucs2 значение ucs2 -> sjis преобразование ucs2 -> cp932 преобразование
005C815F5C
007E7E7E
00A281913F
00A381923F
00AC81CA3F
2015815C815C
201681613F
2212817C3F
22253F8161
301C81603F
FF0D3F817C
FF3C3F815F
FF5E3F8160
FFE03F8191
FFE13F8192
FFE23F81CA

Пользователи любых японских наборов символов должны знать, что использование опций --character-set-client-handshake (или --skip-character-set-client-handshake) имеет важный эффект.

10.11. MySQL 5 FAQ: поддержка наборов символов CJK

Этот набор вопросов происходит из опыта поддержки MySQL в обработке запросов относительно проблем кириллицы и CJK (Chinese-Japanese-Korean).

10.11.1: Я вставил символы CJK в мою таблицу. Почему SELECT отображает их как символы ??

Эта проблема обычно из-за установки в MySQL, который не соответствует параметрам настройки для прикладной программы или операционной системы. Имеются некоторые общие шаги для исправления этих типов проблем:

10.11.2: Какие китайские (GB) наборы символов понимает MySQL?

MySQL поддерживает два общих варианта GB GB ( Guojia Biaozhun или национального эталона) набора символов, которые являются официальными в КНР: gb2312 и gbk. Иногда люди пробуют вставлять символы gbk в gb2312, и это работает в большинстве случаев, потому что gbk является надмножеством gb2312, но в конечном счете они пробуют вставлять старые китайские символы, и это не работает (см. Глюк #16072).

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

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.

Имя символа ucs2sjis cp932ujis eucjpms
BROKEN BAR00A6 3F3F8FA2C3 3F
FULLWIDTH BROKEN BARFFE4 3FFA553F 8FA2
YEN SIGN00A53F 3F203F
FULLWIDTH YEN SIGNFFE5 818F818FA1EF 3F
TILDE007E7E 7E7E7E
OVERLINE203E3F 3F203F
HORIZONTAL BAR2015815C 815CA1BD A1BD
EM DASH20143F 3F3F3F
REVERSE SOLIDUS005C 815F5C5C 5C
FULLWIDTH ""FF3C3F 815F3F A1C0
WAVE DASH301C8160 3FA1C1 3F
FULLWIDTH TILDEFF5E3F 81603F A1C1
DOUBLE VERTICAL LINE2016 81613FA1C2 3F
PARALLEL TO22253F 81613F A1C2
MINUS SIGN2212817C 3FA1DD 3F
FULLWIDTH HYPHEN-MINUSFF0D 3F817C 3FA1DD
CENT SIGN00A28191 3FA1F1 3F
FULLWIDTH CENT SIGNFFE0 3F81913F A1F1
POUND SIGN00A38192 3FA1F2 3F
FULLWIDTH POUND SIGNFFE1 3F81923F A1F2
NOT SIGN00AC 81CA3FA2CC 3F
FULLWIDTH NOT SIGNFFE23F 81CA3FA2CC

Теперь рассмотрите эту часть таблицы:

ucs2 sjiscp932
NOT SIGN00AC 81CA3F
FULLWIDTH NOT SIGNFFE2 3F81CA

Это означает, что 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 (┬е)?

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

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)

Имеются несколько вещей, которые надлежит понять здесь:

  1. Факт, что это является предупреждением, а не ошибкой, характерным для MySQL. Мы предпочитаем пробовать сделать то, что можем, чтобы получить метод наилучшего приближения, чем отказываться.

  2. Символ ц▒М не находится в наборе символов gb2312. Мы рассматривали эту проблему ранее.

  3. По общему признанию сообщение вводит в заблуждение. В этом случае не было никакого усечения: а произошла тривиальная замена символа на вопросительный знак. Авторы уже имели недовольство относительно этого сообщения (см. Глюк #9337 ). Но пока они придумывают кое-что получше, имейте в виду что сообщение 2165 может означать ряд вещей.

  4. С 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?

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




Спонсоры:
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2021 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру