SQL语句中的校验规则强制性
在绝大多数语句中,很明显MySQL使用什么校验规则来解决比较操作。例如,在以下情况下,应该清楚校验规则是column的校验规则x
:
SELECT xFROM TORDER BY x;SELECT xFROM TWHERE x = x;SELECT DISTINCT xFROM T;
但是,对于多个操作数,可能会有歧义。例如:
SELECT xFROM TWHERE 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_column
会utf8
在连接前自动转换为。- 对于具有来自相同字符集但混合使用
_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_connection
和collation_connection
系统变量确定的字符集和校验规则。请参见“表达式评估中的类型转换”。