Ответ 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