mysql utf8_general_ci 区分大小写

2024-06-26

我有一个 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 中发生的情况)same表示的字符串不同的编码,二进制比较无法理解,但二进制排序规则可以。正如下面记录的Unicode 字符集 http://dev.mysql.com/doc/en/charset-unicode-sets.html:

“按字符的代码值排序”和“按字符的二进制表示形式排序”之间存在差异,这种差异仅出现在utf16_bin,因为代理人。

假设utf16_bin(二进制排序规则utf16)是“逐字节”而不是“逐字符”的二进制比较。如果是这样的话,字符的顺序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 and utf16_bin是相同的顺序。这与 UCS_BASIC 排序规则的 SQL:2008 标准要求一致:“UCS_BASIC 是一种排序规则,其中排序完全由要排序的字符串中字符的 Unicode 标量值确定。它适用于 UCS 字符库。由于每个字符库都是 UCS 库的子集,因此 UCS_BASIC 排序规则可能适用于每个字符集。注 11:字符的 Unicode 标量值是被视为无符号整数的代码点。”

因此,如果涉及这些列的比较将always区分大小写,您应该将列的排序规则设置为utf8_bin(这样即使您忘记在查询中另外指定,它们也会保持区分大小写);或者如果只有特定查询区分大小写,您可以指定utf8_bin应该使用排序规则COLLATE关键词:

SELECT * FROM table WHERE id = 'iSZ6fX' COLLATE utf8_bin
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mysql utf8_general_ci 区分大小写 的相关文章

随机推荐