10.2.2 UTF-8(用于元数据)

元数据是“关于数据的数据”。描述数据库的任何内容(而不是数据库的内容)都是元数据。因此,列名,数据库名,用户名,版本名以及SHOW的大多数字符串结果都是元数据。 INFORMATION_SCHEMA中 table 的内容也是如此,因为按定义这些 table 包含有关数据库对象的信息。

元数据的 table 示形式必须满足以下要求:

  • 所有元数据必须使用相同的字符集。否则,INFORMATION_SCHEMA中的 table 的SHOW语句或SELECT语句都将无法正常工作,因为这些操作结果的同一列中的不同行将使用不同的字符集。

  • 元数据必须包含所有语言的所有字符。否则,用户将无法使用自己的语言命名列和 table。

为了满足这两个要求,MySQL 将元数据存储在 Unicode 字符集(即 UTF-8)中。如果您从不使用带重音或非拉丁字符,则不会造成任何干扰。但是,如果这样做,您应该知道元数据位于 UTF-8 中。

元数据要求意味着USER()CURRENT_USER()SESSION_USER()SYSTEM_USER()DATABASE()VERSION()函数的返回值默认情况下具有 UTF-8 字符集。

服务器将character_set_system系统变量设置为元数据字符集的名称:

mysql> SHOW VARIABLES LIKE 'character_set_system';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| character_set_system | utf8  |
+----------------------+-------+

使用 Unicode 存储元数据不是**table 示服务器默认返回character_set_system字符集中的列标题和DESCRIBE函数的结果。当使用SELECT column1 FROM t时,名称column1本身会以character_set_results系统变量的值(默认值为utf8)确定的字符集从服务器返回到 Client 端。如果希望服务器将元数据结果传递回不同的字符集,请使用SET NAMES语句强制服务器执行字符集转换。 SET NAMES设置character_set_results和其他相关的系统变量。 (请参见第 10.4 节“连接字符集和排序规则”。)或者,Client 端程序可以在从服务器接收到结果之后执行转换。Client 端执行转换效率更高,但是此选项并非始终对所有 Client 端都可用。

如果character_set_results设置为NULL,则不执行任何转换,并且服务器使用其原始字符集(由character_set_system指示的字符集)返回元数据。

从服务器返回到 Client 端的错误消息将与元数据一样自动转换为 Client 端字符集。

如果您正在(例如)使用USER()函数在单个语句中进行比较或赋值,请不要担心。 MySQL 为您执行一些自动转换。

SELECT * FROM t1 WHERE USER() = latin1_column;

之所以可行,是因为在比较之前latin1_column的内容会自动转换为 UTF-8.

INSERT INTO t1 (latin1_column) SELECT USER();

之所以有效,是因为分配之前USER()的内容会自动转换为latin1

尽管自动转换不在 SQL 标准中,但该标准确实指出,每个字符集(就支持的字符而言)都是 Unicode 的“子集”。因为众所周知的原则是“适用于超集的内容可以适用于子集”,所以我们认为 Unicode 的排序规则可以适用于与非 Unicode 字符串的比较。有关字符串强制的更多信息,请参见第 10.8.4 节“table 达式中的排序规则强制性”