我有一个mysql数据库,其中我使用utf8_general_ci(不区分大小写),在我的表中我有一些像ID这样的列与区分大小写的数据(例如:'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并在php查询中使用“BINARY”,例如:
mysqli_query( $link, "SELECT * FROM table WHERE BINARY id = 'iSZ6fX'" );
答案 0 :(得分:14)
最好使用utf8_bin
归类,因为即使在UTF-8中不可能,在一般情况下理论上可能(例如UTF-16发生)相同的字符串由不同的编码表示,二进制比较不理解,但二进制校对会。正如Unicode Character Sets所述:
“按字符的代码值排序”和“按字符的二进制表示排序”之间存在差异,这种区别只出现
utf16_bin
,因为有代理。假设
utf16_bin
(utf16
的二进制排序规则)是“逐字节”的二进制比较,而不是“逐个字符”。如果是这样,则utf16_bin
中的字符顺序为utf8_bin
1}}与E000-FFFF
中的顺序不同。例如,下图显示了两个罕见的字符。第一个字符在0xff9d
范围内,因此它大于代理但小于补充。第二个字符是补充。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图表中的两个字符按代码点值排序,因为
0x10384
<utf8
。它们按0xef
值排序,因为0xf0
<utf16
。但是,如果我们使用逐字节比较,它们不会按0xff
值排序,因为0xd8
>utf16_bin
。所以MySQL的
utf16
校对不是“逐字节”。它是“按代码点”。当MySQL在utf8_bin
中看到一个补充字符编码时,它会转换为字符的代码点值,然后比较。因此,utf16_bin
和utf8_bin
排序相同。这与UCS_BASIC排序规则的SQL:2008标准要求一致:“UCS_BASIC是一种排序规则,其排序完全取决于要排序的字符串中字符的Unicode标量值。它适用于UCS角色曲目。由于每个字符集都是UCS指令集的子集,因此UCS_BASIC校对可能适用于每个字符集。注11:字符的Unicode标量值是其代码点,被视为无符号整数。“
因此,如果涉及这些列的比较总是区分大小写,则应将列的排序规则设置为utf8_bin
(这样即使您忘记指定它们也会保持区分大小写否则在你的查询中);或者,如果只有特定查询区分大小写,您可以指定使用COLLATE
关键字来使用SELECT * FROM table WHERE id = 'iSZ6fX' COLLATE utf8_bin
排序规则:
{{1}}
答案 1 :(得分:1)
最好使用带有&utff8_bin'的列。而不是在查询中指定条件,因为它减少了错误的可能性。
答案 2 :(得分:0)
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