15

我有一个 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'" );
4

3 回答 3

18

最好使用utf8_bin排序规则,因为即使在 UTF-8 中不可能,但在一般情况下,理论上可以(例如 UTF-16 发生的情况)用不同的编码表示相同的字符串,这二进制比较不会理解,但二进制排序规则会。如Unicode Character Sets下所述:

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

假设utf16_bin( 的二进制排序规则utf16)是“逐字节”而不是“逐字符”的二进制比较。如果是这样,则 in 中的字符顺序utf16_bin将与 in 中的顺序不同utf8_bin。例如,下图显示了两个稀有字符。第一个字符在 rangeE000-FFFF中,因此它大于代理项但小于补充项。第二个字符是补充。

码点 字符 utf8 utf16
---------- --------- ---- -----
0FF9D 半宽片假名字母 N EF BE 9D FF 9D
10384 乌加里特字母 DELTA F0 90 8E 84 D8 00 DF 84

图表中的两个字符按代码点值排序,因为0xff9d< 0x10384。它们按utf8值排序,因为0xef< 0xf0utf16但是如果我们使用逐字节比较,它们不是按值排序的,因为0xff> 0xd8

所以 MySQL 的utf16_bin排序规则不是“逐字节”的。它是“按代码点”。当 MySQL 在 中看到补充字符编码时utf16,它会转换为字符的代码点值,然后进行比较。因此,utf8_binutf16_bin是相同的排序。这与 UCS_BASIC 排序规则的 SQL:2008 标准要求一致:“UCS_BASIC 是一种排序规则,其中排序完全由正在排序的字符串中字符的 Unicode 标量值确定。它适用于 UCS 字符库。由于每个字符库都是 UCS 库的子集,因此 UCS_BASIC 排序规则可能适用于每个字符集。注 11:字符的 Unicode 标量值是其代码点,被视为无符号整数。”</p>

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

SELECT * FROM table WHERE id = 'iSZ6fX' COLLATE utf8_bin
于 2013-09-11T09:56:50.200 回答
1

最好使用带有 'utf8_bin' 的列,而不是在查询中指定条件,因为它可以减少出错的机会。

于 2013-09-11T09:52:25.003 回答
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
于 2013-09-11T09:53:22.440 回答