# 10.8.4 表达式中的排序规则强制

在绝大多数语句中,很明显 MySQL 使用什么排序规则来解决比较操作。例如,在以下情况下,应该清楚排序规则是列的排序规则x

SELECT x FROM T ORDER BY x;
SELECT x FROM T WHERE x = x;
SELECT DISTINCT x FROM T;

但是,对于多个操作数,可能会产生歧义。例如,此语句执行列之间的比较x和字符串文字'是'

SELECT x FROM T WHERE x = 'Y';

如果x'是'具有相同的排序规则,用于比较的排序规则没有歧义。但是如果他们有不同的排序规则,比较是否应该使用排序规则x, 或'是'?两个都x'是'有排序规则,那么哪个排序规则优先?

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

为了解决此类问题,MySQL 检查是否可以将一项的排序规则强制转换为另一项的排序规则。MySQL 分配强制值如下:

  • 显式整理子句的强制力为 0(根本不强制)。

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

  • 列或存储的例程参数或局部变量的排序规则具有 2 的强制力。

  • 一个“系统常量”(由函数返回的字符串,例如用户()要么版本()) 的强制力为 3。

  • 文字的排序规则具有 4 的强制力。

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

  • 空值或派生自的表达式空值强制力为 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使用排序规则。这类似于混合非二进制和二进制字符串的操作如何将操作数评估为二进制字符串,应用于排序规则而不是数据类型。

    尽管自动转换不在 SQL 标准中,但该标准确实说每个字符集(就支持的字符而言)都是 Unicode 的“子集”。因为“适用于超集的内容可以适用于子集”是众所周知的原则,我们相信 Unicode 的排序规则可以适用于与非 Unicode 字符串的比较。更一般地说,MySQL 使用字符集库的概念,它有时可用于确定字符集之间的子集关系,并启用操作中的操作数转换,否则会产生错误。看第 10.2.1 节,“字符集曲目”.

    下表说明了上述规则的一些应用。

比较 使用的排序规则
列 1 = 'A' 使用排序规则第 1 列
column1 = 'A' 整理 x 使用排序规则'A' 整理 x
column1 整理 x = 'A' 整理 y 错误

要确定字符串表达式的可强制性,请使用强制力()功能(见第 12.16 节,“信息功能”):

mysql> SELECT COERCIBILITY(_utf8'A' COLLATE utf8_bin);
        -> 0
mysql> SELECT COERCIBILITY(VERSION());
        -> 3
mysql> SELECT COERCIBILITY('A');
        -> 4
mysql> SELECT COERCIBILITY(1000);
        -> 5
mysql> SELECT COERCIBILITY(NULL);
        -> 6

用于将数值或时间值隐式转换为字符串,例如发生在参数中1在表达式中连接(1,'abc'),结果是一个字符(非二进制)字符串,其字符集和排序规则由字符集连接collat​​ion_connection系统变量。看第 12.3 节,“表达式求值中的类型转换”.