元数据 是 “关于数据的数据。” 任何描述数据库的信息——相比于数据库的 内容 ——都是元数据。因此,列名、数据库名、用户名、版本名和来自 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 存储元数据并不意味着服务器将列标题和 DESCRIBE
函数的结果以 character_set_system
字符集返回默认值。当您使用 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()
函数进行比较或赋值within 单个语句,不要担心。MySQL 将为您执行一些自动转换。
SELECT * FROM t1 WHERE USER() = latin1_column;
这 works,因为 latin1_column
的内容将在比较之前自动转换为 UTF-8。
INSERT INTO t1 (latin1_column) SELECT USER();
这 works,因为 USER()
的内容将在赋值之前自动转换为 latin1
。
尽管自动转换不在SQL标准中,但标准规定每个字符集(在支持的字符方面)是 Unicode 的一个 “子集”。因为众所周知的原则是 “适用于超集的也适用于子集,” 我们认为 Unicode 的排序规则可以应用于与非 Unicode 字符串的比较。有关字符串强制的更多信息,请参阅 第 12.8.4 节,“表达式中的排序规则强制”。