元数据 是 “关于数据的数据。” 任何 描述 数据库的东西,而不是数据库的 内容,都是元数据。因此,列名、数据库名、用户名、版本名以及大多数来自 SHOW
的字符串结果都是元数据。 INFORMATION_SCHEMA
中的表内容也是如此,因为这些表定义上包含有关数据库对象的信息。
元数据的表示必须满足以下要求
为了满足这两个要求,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 | utf8mb3 |
+----------------------+---------+
使用 Unicode 存储元数据 并不 意味着服务器默认情况下会以 character_set_system
字符集返回列标题和 DESCRIBE
函数的结果。当您使用 SELECT column1 FROM t
时,名称 column1
本身将从服务器返回给客户端,其字符集由 character_set_results
系统变量的值确定,该变量的默认值为 utf8mb4
。如果您希望服务器以不同的字符集传递元数据结果,请使用 SET NAMES
语句强制服务器执行字符集转换。 SET NAMES
设置 character_set_results
和其他相关系统变量。(参见 第 12.4 节“连接字符集和排序规则”。)或者,客户端程序可以在从服务器接收结果后执行转换。客户端执行转换效率更高,但此选项并非所有客户端都支持。
如果 character_set_results
设置为 NULL
,则不会执行任何转换,服务器将使用其原始字符集(由 character_set_system
指示的字符集)返回元数据。
从服务器返回给客户端的错误消息将自动转换为客户端字符集,与元数据一样。
如果您正在使用(例如)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 字符串的比较。有关字符串强制转换的更多信息,请参见 第 12.8.4 节“表达式中的排序规则强制转换”。