每个字符串文字都有一个字符集和一个排序规则。
对于简单语句 SELECT ',字符串具有由 字符串'character_set_connection 和 collation_connection 系统变量定义的连接默认字符集和排序规则。
字符串文字可以有一个可选的字符集介绍器和 COLLATE 子句,以将其指定为使用特定字符集和排序规则的字符串。
[_charset_name]'string' [COLLATE collation_name]_ 表达式在形式上称为 介绍器。它告诉解析器,“后面的字符串使用字符集 charset_namecharset_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_namecharset_name和排序规则collation_name。collation_name必须是charset_name允许的排序规则。如果指定了
_charset_name但未指定COLLATE,则使用字符集charset_name及其默认排序规则。要查看每个字符集的默认排序规则,请使用SHOW CHARACTER SET语句或查询INFORMATION_SCHEMACHARACTER_SETS表。如果未指定
_charset_name但指定了COLLATE,则使用由collation_namecharacter_set_connection系统变量给出的连接默认字符集和排序规则collation_name。collation_name必须是连接默认字符集允许的排序规则。否则(既未指定
_charset_name也未指定COLLATE),则使用由collation_namecharacter_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 介绍器不会影响转义处理。