每个字符串文字都有一个字符集和一个排序规则。
对于简单语句 SELECT '
,字符串具有由 字符串
'character_set_connection
和 collation_connection
系统变量定义的连接默认字符集和排序规则。
字符串文字可以有一个可选的字符集介绍器和 COLLATE
子句,以将其指定为使用特定字符集和排序规则的字符串。
[_charset_name]'string' [COLLATE collation_name]
_
表达式在形式上称为 介绍器。它告诉解析器,“后面的字符串使用字符集 charset_name
charset_name
。” 与 CONVERT()
不同,介绍器不会将字符串更改为介绍器字符集。它不会更改字符串值,尽管可能会发生填充。介绍器只是一个信号。请参阅 第 12.3.8 节 “字符集介绍器”。
示例
SELECT 'abc';
SELECT _latin1'abc';
SELECT _binary'abc';
SELECT _utf8mb4'abc' COLLATE utf8mb4_danish_ci;
字符集介绍器和 COLLATE
子句是根据标准 SQL 规范实现的。
MySQL 按以下方式确定字符串文字的字符集和排序规则:
如果同时指定了
_charset_name
和COLLATE
,则使用字符集collation_name
charset_name
和排序规则collation_name
。collation_name
必须是charset_name
允许的排序规则。如果指定了
_charset_name
但未指定COLLATE
,则使用字符集charset_name
及其默认排序规则。要查看每个字符集的默认排序规则,请使用SHOW CHARACTER SET
语句或查询INFORMATION_SCHEMA
CHARACTER_SETS
表。如果未指定
_charset_name
但指定了COLLATE
,则使用由collation_name
character_set_connection
系统变量给出的连接默认字符集和排序规则collation_name
。collation_name
必须是连接默认字符集允许的排序规则。否则(既未指定
_charset_name
也未指定COLLATE
),则使用由collation_name
character_set_connection
和collation_connection
系统变量给出的连接默认字符集和排序规则。
示例
具有
latin1
字符集和latin1_german1_ci
排序规则的非二进制字符串:SELECT _latin1'Müller' COLLATE latin1_german1_ci;
具有
utf8mb4
字符集及其默认排序规则(即utf8mb4_0900_ai_ci
)的非二进制字符串:SELECT _utf8mb4'Müller';
具有
binary
字符集及其默认排序规则(即binary
)的二进制字符串:SELECT _binary'Müller';
具有连接默认字符集和
utf8mb4_0900_ai_ci
排序规则的非二进制字符串(如果连接字符集不是utf8mb4
,则失败):SELECT 'Müller' COLLATE utf8mb4_0900_ai_ci;
具有连接默认字符集和排序规则的字符串:
SELECT 'Müller';
介绍器指示后面字符串的字符集,但不改变解析器在字符串中执行转义处理的方式。解析器始终根据 character_set_connection
给出的字符集来解释转义符。
以下示例显示,即使存在介绍器,转义处理也是使用 character_set_connection
进行的。这些示例使用 SET NAMES
(它会更改 character_set_connection
,如 第 12.4 节 “连接字符集和排序规则” 中所述),并使用 HEX()
函数显示生成的字符串,以便可以看到确切的字符串内容。
示例 1
mysql> SET NAMES latin1;
mysql> SELECT HEX('à\n'), HEX(_sjis'à\n');
+------------+-----------------+
| HEX('à\n') | HEX(_sjis'à\n') |
+------------+-----------------+
| E00A | E00A |
+------------+-----------------+
此处,à
(十六进制值 E0
)后跟 \n
,即换行符的转义序列。使用 character_set_connection
的值 latin1
解释转义序列,以生成文字换行符(十六进制值 0A
)。即使对于第二个字符串也会发生这种情况。也就是说,_sjis
介绍器不会影响解析器的转义处理。
示例 2
mysql> SET NAMES sjis;
mysql> SELECT HEX('à\n'), HEX(_latin1'à\n');
+------------+-------------------+
| HEX('à\n') | HEX(_latin1'à\n') |
+------------+-------------------+
| E05C6E | E05C6E |
+------------+-------------------+
此处,character_set_connection
为 sjis
,这是一种字符集,其中 à
后跟 \
的序列(十六进制值 05
和 5C
)是一个有效的多字节字符。因此,字符串的前两个字节被解释为一个 sjis
字符,而 \
不被解释为转义字符。后面的 n
(十六进制值 6E
)不被解释为转义序列的一部分。即使对于第二个字符串也是如此;_latin1
介绍器不会影响转义处理。