utf8_general_ci中的mysql区分大小写

Posted

技术标签:

【中文标题】utf8_general_ci中的mysql区分大小写【英文标题】:mysql case sensitive in utf8_general_ci 【发布时间】:2013-09-15 06:40:13 【问题描述】:

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

【问题讨论】:

data 区分大小写,还是单个 query 区分大小写?例如,除了那个之外,您通常会执行不区分大小写的查询吗?这应该会告诉你答案! 【参考方案1】:

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

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

最好使用utf8_bin 排序规则,因为即使在 UTF-8 中不可能,但在一般情况下,对于 相同 字符串由 不同的 编码表示,二进制比较无法理解,但二进制排序规则可以。如Unicode Character Sets 中所述:

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

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

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

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

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

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

SELECT * FROM table WHERE id = 'iSZ6fX' COLLATE utf8_bin

【讨论】:

因此,如果我总是需要区分大小写的数据,最好仅在此列中设置 utf8_bin,并将 utf8_general_ci 保留在所有其他列以及表和数据库中 utf8_general_ci。否则,如果只有少数查询区分大小写,即使列排序规则是 utf8_general_ci,也只需在查询中添加 COLLATE utf8_bin。对吗?

以上是关于utf8_general_ci中的mysql区分大小写的主要内容,如果未能解决你的问题,请参考以下文章

MySQL_编码utf8_bin和utf8_general_ci的区别

MySQL系列:utf8_bin和utf8_general_ci编码的区别

具有与 MySQL 的 utf8_general_ci 排序相似特征的 Java Collat​​or

MySQL

使用 utf8_general_ci 排序规则和 utf8 字符集服务器的德语变音符号的搜索结果区分大小写

MySQL 字段内容区分大小写