我有一个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'" );
3 回答
最好使用
utf8_bin
校对,因为即使在UTF-8中不可能,在一般情况下理论上可能(例如UTF-16发生)同一个字符串由不同的编码表示,二进制比较不会理解,但二进制整理会 . 如Unicode Character Sets所述: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
(这样即使您忘记在查询中另行指定,它们仍将保持区分大小写);或者如果只有特定查询区分大小写,则可以指定使用COLLATE
关键字来使用utf8_bin
排序规则:最好使用带有'utf8_bin'的列而不是在查询中指定条件,因为它可以减少出错的可能性 .
BINARY作为列属性的效果与MySQL 4.1之前的效果不同 . 以前,BINARY导致一个被视为二进制字符串的列 . 二进制字符串是一个没有字符集或排序规则的字节字符串,它与具有二进制排序规则的非二进制字符串不同 .
但现在
BINARY运算符将其后面的字符串转换为二进制字符串 . 这是一种简单的方法,可以逐个字节而不是逐个字符地强制进行比较 . BINARY也会导致尾随空格很重要 . BINARY str是CAST的简写(str AS BINARY) .
字符列定义中的BINARY属性具有不同的效果 . 使用BINARY属性定义的字符列将分配列字符集的二进制排序规则 . 每个字符集都有一个二进制排序规则 . 例如,latin1字符集的二进制排序规则是latin1_bin,因此如果表默认字符集是latin1,则这两个列定义是等效的: