Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Collation Coercibility in Expressions

12.8.4 表达式中的排序规则强制性

在大多数语句中,MySQL 使用的排序规则是很明显的。例如,在以下情况下,排序规则应该是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 的排序规则还是'Y' 的排序规则?x'Y' 都具有排序规则,所以哪个排序规则优先?

混合排序规则也可能出现在非比较上下文中。例如,多参数连接操作如CONCAT(x,'Y') 将其参数组合成一个字符串。结果应该具有什么排序规则?

为了解决这些问题,MySQL 检查是否可以将某个项目的排序规则强制转换到另一个项目的排序规则。MySQL 将 coercibility 值分配如下:

  • 明确的COLLATE 子句具有 0 的强制性(不能强制转换)。

  • 两个字符串具有不同排序规则的连接操作具有 1 的强制性。

  • 列、存储程序参数或本地变量的排序规则具有 2 的强制性。

  • 一个系统常量(由函数如USER()VERSION()返回的字符串)具有强制性为3。

  • 字面量的排序规则具有强制性为4。

  • 数字或时间值的排序规则具有强制性为5。

  • NULL或来自NULL的表达式具有强制性为6。

MySQL 使用强制性值以解决歧义:

  • 使用最低强制性的排序规则。

  • 如果两边都相同,

    • 如果两边都是Unicode字符集,或者两边都不是Unicode字符集,那么是错误。

    • 如果有一边有Unicode字符集,一边没有Unicode字符集,那么Unicode字符集获胜,并对非Unicode字符集自动进行转换。例如,以下语句不返回错误:

      SELECT CONCAT(utf8mb4_column, latin1_column) FROM t1;

      它返回结果具有utf8mb4字符集和与utf8mb4_column相同的排序规则。latin1_column值自动转换为utf8mb4然后进行连接。

    • 对于同一字符集但混合了_bin排序规则和_ci_cs排序规则的操作,使用_bin排序规则。这类似于混合非二进制和二进制字符串的操作,对collations而不是数据类型进行评估。

虽然自动转换不在SQL标准中,但是标准确实说每个字符集都是Unicode的一个子集。因为是众所周知的原则对超集也可以应用于子集,我们认为Unicode的排序规则可以用于与非Unicode字符串的比较。更广泛地说,MySQL 使用字符集词汇,可以有时用来确定字符集之间的子集关系,从而使操作中可能出现错误的操作项进行转换。见第12.2.1节,“字符集词汇”

以下表格展示了前面规则的应用。

Comparison Collation Used
column1 = 'A' 使用column1的排序规则
column1 = 'A' COLLATE x 使用'A'的排序规则
column1 COLLATE x = 'A' COLLATE y 错误

要确定字符串表达式的强制性,使用COERCIBILITY()函数(见第14.15节,“信息函数”):

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

对于隐式将数字或时间值转换为字符串的操作,例如在表达式CONCAT(1, 'abc')中对1的处理结果是一个字符(非二进制)字符串,它的字符集和排序规则由character_set_connectioncollation_connection系统变量确定。详见第14.3节,“表达式求值中的类型转换”