我有一个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'" );
最好使用 utf8_bin
整理,因为,即使在UTF-8中不可能,在一般情况下理论上可能(例如UTF-16发生) 相同 要表示的字符串 不同 编码,二进制比较不会理解,但二进制校对会。如下所述 Unicode字符集:
“按字符的代码值排序”和“按字符的二进制表示排序”之间存在差异,这种差异仅出现在 utf16_bin
,因为代理人。
假设 utf16_bin
(二进制排序规则 utf16
)是一个二进制比较“逐字节”而不是“逐个字符。”如果是这样,字符的顺序 utf16_bin
会与订单不同 utf8_bin
。例如,下图显示了两个罕见的字符。第一个字符在范围内 E000-FFFF
,所以它大于代理人但不足以补充。第二个字符是补充。
代码点字符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
是相同的顺序。这与UCS_BASIC排序规则的SQL:2008标准要求一致:“UCS_BASIC是一种排序规则,其排序完全取决于要排序的字符串中字符的Unicode标量值。它适用于UCS角色曲目。由于每个字符集都是UCS指令集的子集,因此UCS_BASIC校对可能适用于每个字符集。注11:字符的Unicode标量值是其代码点,被视为无符号整数。“
因此,如果涉及这些列的比较将会 总是 区分大小写,您应该将列的排序规则设置为 utf8_bin
(即使您忘记在查询中另行指定,它们仍将保持区分大小写);或者如果只有特定查询区分大小写,您可以指定 utf8_bin
应该使用排序规则 COLLATE
关键词:
SELECT * FROM table WHERE id = 'iSZ6fX' COLLATE utf8_bin
最好使用带有'utf8_bin'的列而不是在查询中指定条件,因为它可以减少出错的可能性。
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