Регистр mysql в utf8_general_ci

У меня есть база данных mysql, где я использую utf8_general_ci (это не зависит от регистра), и в моих таблицах у меня есть некоторые столбцы, такие как идентификатор с чувствительными к регистру данными (пример: "iSZ6fX" или "AscSc2" )

В отличие от верхнего регистра с нижним регистром лучше установить на этих столбцах только utf8_bin, например:

CREATE TABLE  `test` (
`id` VARCHAR( 32 ) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL ,
`value1` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
) ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_general_ci

Или используйте utf8_general_ci для всех столбцов и используйте "BINARY" в запросе php, например:

mysqli_query( $link, "SELECT * FROM table WHERE BINARY id = 'iSZ6fX'" );

Ответ 1

Лучше использовать сортировку utf8_bin, потому что, хотя это невозможно в UTF-8, в общем случае теоретически возможно (например, с UTF-16) для той же строки, которая будет представлена разными кодировками, которые двоичное сравнение не понимало бы, но двоичная сортировка. Как описано в Unicode Character Sets:

Существует различие между "упорядочением по значению символьного кода" и "упорядочением по двоичному представлению символов", разница, которая появляется только с utf16_bin, из-за суррогатов.

Предположим, что utf16_bin (двоичная сортировка для utf16) была двоичным сравнением "byte by byte", а не "character by character". Если бы это было так, порядок символов в utf16_bin отличался бы от порядка в utf8_bin. Например, на следующей диаграмме показаны два редких символа. Первый символ находится в диапазоне E000-FFFF, поэтому он больше суррогата, но меньше, чем дополнительный. Второй символ является дополнительным.

Code point  Character                    utf8         utf16
----------  ---------                    ----         -----
0FF9D       HALFWIDTH KATAKANA LETTER N  EF BE 9D     FF 9D
10384       UGARITIC LETTER DELTA        F0 90 8E 84  D8 00 DF 84

Два символа на графике упорядочены по кодовой точке, потому что 0xff9d < 0x10384. И они соответствуют по значению utf8, потому что 0xef < 0xf0. Но они не соответствуют значению utf16, если мы используем байтовое сравнение, потому что 0xff > 0xd8.

Итак, MySQL utf16_bin сортировка не является байтом по байтам. Это "по кодовой точке". Когда MySQL видит кодировку дополнительного символа в utf16, он преобразуется в значение кодовой точки символа, а затем сравнивает. Поэтому utf8_bin и utf16_bin являются одинаковыми. Это согласуется с стандартным требованием SQL: 2008 для сортировки UCS_BASIC: "UCS_BASIC - это сортировка, в которой упорядочение полностью определяется скалярными значениями символов Юникода символов в сортируемых строках. Оно применимо к репертуару символов UCS. Поскольку каждый репертуар персонажа является подмножеством репертуара UCS, сопоставление UCS_BASIC потенциально применимо к каждому набору символов. ПРИМЕЧАНИЕ 11: Сканирующее значение Unicode символа является его кодовой точкой, рассматриваемой как целое число без знака."

Поэтому, если сравнения с этими столбцами всегда будут чувствительны к регистру, вы должны установить сопоставление столбцов на utf8_bin (чтобы они оставались чувствительными к регистру, даже если вы забыли указать иначе в своем запросе); или если только определенные запросы чувствительны к регистру, вы можете указать, что сортировка utf8_bin должна использоваться с использованием ключевого слова COLLATE:

SELECT * FROM table WHERE id = 'iSZ6fX' COLLATE utf8_bin

Ответ 2

Лучше использовать столбцы с "utf8_bin", а не указывать условие в запросе, потому что это уменьшает вероятность ошибок.

Ответ 3

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

Но сейчас

Оператор BINARY выставляет строку, следующую за ней, в двоичную строку. Это простой способ заставить сравнивать байтов по байтам, а не по характеру. BINARY также приводит к значительным значениям конечных пробелов. BINARY str является сокращением для CAST (str AS BINARY).

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

CHAR(10) BINARY

CHAR(10) CHARACTER SET latin1 COLLATE latin1_bin