每个字符字符串文字都有一个字符集和一个排序规则。
对于简单的语句 SELECT '
, 字符串具有连接默认字符集和排序规则,定义了 string
'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
引入符不影响转义处理。