• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • SQL语句中的校验规则强制性

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

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

    但是,对于多个操作数,可能会有歧义。例如:

    SELECT x FROM T WHERE x = 'Y';
    

    比较是否应该使用列x或字符串文字的校验规则'Y'?双方x'Y'有校验规则,所以其校验的优先级?

    校验规则的混合也可能在比较之外的其他情况下发生。例如,多参数串联操作(例如,CONCAT(x,'Y')组合其参数以产生单个字符串)。结果应该具有什么校验规则?

    为了解决这样的问题,MySQL检查是否可以将一项的校验规则强制为另一项的校验规则。MySQL分配强制性值如下:

    • 显式COLLATE子句的强制性为0(根本不可强制)。
    • 具有不同校验规则的两个字符串的串联的强制性为1。
    • 列或存储的例程参数或局部变量的校验规则的强制性为2。
    • 阿“系统常数”(由功能,例如返回的字符串USER()VERSION())具有为3的可压缩性。
    • 文字的校验规则的强制性为4。
    • 数字或时间值的校验规则的强制性为5。
    • NULL或衍生自的表达式NULL的矫顽力为6。

    MySQL使用强制性值和以下规则来解决歧义:

    • 使用强制性最低的校验规则。
    • 如果双方具有相同的强制性,则:

      • 如果双方都是Unicode,或者双方都不是Unicode,则错误。
      • 如果其中一方具有Unicode字符集,而另一方具有非Unicode字符集,则具有Unicode字符集的一方获胜,并且自动字符集转换将应用于非Unicode一方。例如,以下语句不返回错误:

        SELECT CONCAT(utf8_column, latin1_column) FROM t1;
        

        它返回一个结果,该结果的字符集为utf8,校验规则与相同utf8_column。的值latin1_columnutf8在连接前自动转换为。

      • 对于具有来自相同字符集但混合使用_bin归类和a _ci_cs归类的操作数的运算,将使用归类_bin。这类似于混合非二进制和二进制字符串的操作如何将操作数评估为二进制字符串,不同之处在于它用于校验规则而不是数据类型。

    尽管自动转换不在SQL标准中,但该标准确实指出,每个字符集(就支持的字符而言)都是Unicode 的“子集”。因为众所周知的原则是“适用于超集的内容可以适用于子集”,所以我们认为Unicode的校验规则可以适用于与非Unicode字符串的比较。

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

    比较方式使用的归类
    column1 ='A'使用校验规则column1
    column1 ='A' COLLATE x使用校验规则'A' COLLATE x
    column1 COLLATE x ='A' COLLATE y错误

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

    mysql> SELECT COERCIBILITY('A' COLLATE latin1_swedish_ci);
    -> 0
    mysql> SELECT COERCIBILITY(VERSION());
    -> 3
    mysql> SELECT COERCIBILITY('A');
    -> 4
    mysql> SELECT COERCIBILITY(1000);
    -> 5
    

    对于将数值或时间值隐式转换为字符串的情况(例如1在表达式中的参数中发生的情况)CONCAT(1,'abc'),结果是一个字符(非二进制)字符串,该字符串具有由character_set_connectioncollation_connection系统变量确定的字符集和校验规则。请参见“表达式评估中的类型转换”。