12.2.1 字符集目录
一个字符集的repertoire
是该集中的所有字符。
字符串表达式有一个repertoire
属性,该属性可以取两个值:
-
ASCII
: 表达式只能包含 ASCII 字符,即 Unicode 范围U+0000
到U+007F
。 -
UNICODE
: 表达式可以包含 Unicode 范围U+0000
到U+10FFFF
的字符。这包括基本多语言平面(BMP)范围 (U+0000
到U+FFFF
) 和补充字符外部 BMP 范围 (U+10000
到U+10FFFF
).
ASCII
范围是UNICODE
范围的子集,所以一个字符串具有ASCII
repertoire 可以安全地转换到任何字符串具有UNICODE
repertoire 的字符集,也可以安全地转换到任何是ascii
字符集的子集。(所有 MySQL 字符集都除外 swe7,后者重用一些标点符号为瑞典语带点字母。)
使用词库使得表达式中字符集转换在许多情况下可以避免MySQL返回““非法混合排序”错误,例如当collation强制性规则不足以解决歧义时。关于强制性规则的信息,请参阅第12.8.4节,“表达式中的排序强制性”。
以下讨论提供了示例和词库的使用,描述了词库如何改变字符串表达式的评估:
-
一个字符串常量的词库取决于字符串内容,并可能与字符串字符集的词库不同。考虑这些语句:
SET NAMES utf8mb4; SELECT 'abc'; SELECT _utf8mb4'def';
每个前面的情况中,字符集都是
utf8mb4
,但是字符串实际上不包含任何ASCII范围外的字符,所以它们的词库是ASCII
,而不是UNICODE
。 -
一个具有
ascii
字符集的列因为其字符集而拥有ASCII
词库。在以下表中,c1
拥有ASCII
词库:CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET ascii);
以下示例展示了如何使用词库在错误情况下确定结果:
CREATE TABLE t1 ( c1 CHAR(1) CHARACTER SET latin1, c2 CHAR(1) CHARACTER SET ascii ); INSERT INTO t1 VALUES ('a','b'); SELECT CONCAT(c1,c2) FROM t1;
没有词库,这个错误就会发生:
ERROR 1267 (HY000): Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (ascii_general_ci,IMPLICIT) for operation 'concat'
使用词库,子集到超集(
ascii
到latin1
+---------------+ | CONCAT(c1,c2) | +---------------+ | ab | +---------------+
-
具有一个字符串参数的函数继承自其参数的字符集。结果
UPPER('abc')
的字符集是ASCII
,因为其参数的字符集也是ASCII
。(尽管有_utf8mb4
引数,但字符串'abc'
中没有超出 ASCII 范围的字符。) -
对于返回字符串但不带字符串参数且使用
character_set_connection
作为结果字符集的函数,结果字符集是ASCII
如果character_set_connection
是ascii
,否则是UNICODE
:FORMAT(numeric_column, 4);
使用字符集更改 MySQL 对以下示例的评估方式:
SET NAMES ascii; CREATE TABLE t1 (a INT, b VARCHAR(10) CHARACTER SET latin1); INSERT INTO t1 VALUES (1,'b'); SELECT CONCAT(FORMAT(a, 4), b) FROM t1;
没有字符集,这个错误发生:
ERROR 1267 (HY000): Illegal mix of collations (ascii_general_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation 'concat'
有字符集,返回结果:
+-------------------------+ | CONCAT(FORMAT(a, 4), b) | +-------------------------+ | 1.0000b | +-------------------------+
-
具有两个或更多字符串参数的函数使用最宽的参数字符集作为结果字符集,其中
UNICODE
宽于ASCII
。考虑以下CONCAT()
调用:CONCAT(_ucs2 X'0041', _ucs2 X'0042') CONCAT(_ucs2 X'0041', _ucs2 X'00C2')
对于第一个调用,字符集是
ASCII
因为两个参数都在 ASCII 范围内。对于第二个调用,字符集是UNICODE
因为第二个参数超出 ASCII 范围。 -
函数返回值的字符集和排序规则由影响结果字符集和排序规则的那些参数确定。
IF(column1 < column2, 'smaller', 'greater')
结果字符集是
ASCII
,因为第二个和第三个字符串参数都具有ASCII
字符集。第一个参数对结果字符集无影响,即使表达式使用字符串值。