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
中出现,因为有代理项。假设
码点 字符 utf8 utf16 ---------- --------- ---- ----- 0FF9D 半宽片假名字母 N EF BE 9D FF 9D 10384 乌加里特字母 DELTA F0 90 8E 84 D8 00 DF 84utf16_bin
(utf16
的二进制排序规则)是“逐字节”而不是“逐字符”的二进制比较。如果是这样,utf16_bin
中的字符顺序将与utf8_bin
中的顺序不同。例如,下图显示了两个稀有字符。第一个字符在E000-FFFF
范围内,因此它大于代理项但小于补充项。第二个字符是补充。图表中的两个字符按代码点值排序,因为
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
排序规则:
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 Collator