元数据 是 “关于数据的数据。” 任何 描述 数据库的东西(与数据库的 内容 相反)都是元数据。因此,列名、数据库名、用户名、版本名以及 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 节,“表达式中的排序规则强制性”。