在绝大多数语句中,很明显 MySQL 使用什么排序规则来解决比较操作。例如,在以下情况下,应该明确排序规则是 column 的排序规则x
:
SELECT x FROM T ORDER BY x;
SELECT x FROM T WHERE x = x;
SELECT DISTINCT x FROM T;
但是,对于多个操作数,可能会出现歧义。例如,此语句执行列
x
和字符串文字
之间的比较'Y'
:
SELECT x FROM T WHERE x = 'Y';
如果x
和'Y'
具有相同的排序规则,则用于比较的排序规则没有歧义。但是如果它们有不同的归类,比较应该使用的归类x
还是 of
'Y'
?x
和
都有'Y'
归类,那么哪个归类优先?
在比较以外的上下文中也可能会出现混合排序规则。例如,一个多参数串联操作,例如CONCAT(x,'Y')
将其参数组合起来生成一个字符串。结果应该有什么排序规则?
为了解决这些问题,MySQL 检查是否可以将一项的排序规则强制转换为另一项的排序规则。MySQL 分配强制值如下:
MySQL 使用具有以下规则的强制性值来解决歧义:
使用强制性值最低的排序规则。
如果双方具有相同的强制性,则:
如果两边都是Unicode,或者两边都不是Unicode,都是错误的。
如果一方有 Unicode 字符集,另一方有非 Unicode 字符集,则有 Unicode 字符集的一方获胜,自动字符集转换应用于非 Unicode 一方。例如,以下语句不会返回错误:
SELECT CONCAT(utf8mb4_column, latin1_column) FROM t1;
它返回一个结果,其字符集为
utf8mb4
且排序规则与 相同utf8mb4_column
。的值 在连接之前latin1_column
自动转换为utf8mb4
。_bin
对于具有来自相同字符集但混合排序规则和_ci
or_cs
排序规则 的操作数的操作,使用_bin
排序规则。这类似于混合非二进制和二进制字符串的操作如何将操作数评估为二进制字符串,应用于排序规则而不是数据类型。
尽管自动转换不在 SQL 标准中,但该标准确实表示每个字符集(就支持的字符而言)都是 Unicode 的“子集”。因为“适用于超集的也适用于子集”是众所周知的原则,所以我们认为 Unicode 的排序规则可以适用于与非 Unicode 字符串的比较。更一般地说,MySQL 使用字符集指令表的概念,它有时可用于确定字符集之间的子集关系,并启用操作中的操作数转换,否则会产生错误。请参阅第 10.2.1 节,“字符集指令表”.
下表说明了上述规则的一些应用。
比较 | 使用的排序规则 |
---|---|
column1 = 'A' |
使用排序规则column1 |
column1 = 'A' COLLATE x |
使用排序规则'A' COLLATE x |
column1 COLLATE x = 'A' COLLATE y |
错误 |
要确定字符串表达式的强制性,请使用
COERCIBILITY()
函数(请参阅
第 12.16 节,“信息函数”):
mysql> SELECT COERCIBILITY(_utf8mb4'A' COLLATE utf8mb4_bin);
-> 0
mysql> SELECT COERCIBILITY(VERSION());
-> 3
mysql> SELECT COERCIBILITY('A');
-> 4
mysql> SELECT COERCIBILITY(1000);
-> 5
mysql> SELECT COERCIBILITY(NULL);
-> 6
对于数字或时间值到字符串的隐式转换,例如1
expression中的参数CONCAT(1, 'abc')
,结果是一个字符(非二进制)字符串,其字符集和排序规则由
character_set_connection
和
collation_connection
系统变量确定。请参阅第 12.3 节,“表达式计算中的类型转换”。