10.6. 用于元数据的UTF8
元数据是“关于数据的数据”。描述数据库的任何数据—作为数据库内容的对立面—是元数据。因此,列名、数据库名、用户名、版本名以及从SHOW语句得到的结果中的大部分字符串是元数据。还包括INFORMATION_SCHEMA数据库中的表中的内容,因为定义的那些表存储关于数据库对象的信息。
元数据表述必须满足这些需求:
·全部元数据必须在同一字符集内。否则,对INFORM一个TION_SCHEMA数据库中的表执行的SHOW命令和SELECT查询不能正常工作,因为这些运算结果中的同一列的不同行将会使用不同的字符集。
·元数据必须包括所有语言的所有字符。否则,用户将不能够使用它们自己的语言来命名列和表。
为了满足这两个需求,MySQL使用Unicode字符集存储元数据,即UTF8。如果你从不使用重音字符,这不会导致任何破坏。但如果你使用重音字符,应该注意的是元数据是用UTF8存储。
这意味着,USER()、CURRENT_USER()、DATABASE()和VERSION()函数的返回值被默认设置为UTF8字符集,这与同义函数如SESSION_USER()和SYSTEM_USER()的结果相同。
服务器将character_set_system系统变量设置为元数据字符集的名:
mysql> SHOW VARIABLES LIKE 'character_set_system';
+----------------------+-------+
| Variable_name| Value |
+----------------------+-------+
| character_set_system | utf8 |
+----------------------+-------+
存储元数据使用Unicode并不意味着列头和DESCRIBE函数的结果默认在character_set_system字符集中。当你使用SELECT column1 FROM t语句时,名字为column1的列从服务器返回客户端并使用由SET NAMES语句确定的字符集。更明确地说,使用的字符集是由character_set_results系统变量的值确定的。如果这个系统变量设置为NULL,不执行字符转换,服务器使用最初的字符集(字符集由character_set_system系统变量设置)返回元数据。
如果你希望服务器不使用UTF8字符集返回元数据结果,那么使用SET NAMES语句强制服务器执行字符集转换(见10.3.6节,“连接字符集和校对”),或者在客户端执行转换。在客户端执行转换效率较高,但这种选项并不能使用于全部客户端。
如果你正在一个语句中使用(例如)USER()函数进行比较或赋值,不要担心。MySQL为你执行一些原子转换。
SELECT * FROM Table1 WHERE USER() = latin1_column;
这是可以的,因为在比较之前latin1_column列的内容会自动转换到UTF8。
INSERT INTO Table1 (latin1_column) SELECT USER();
这是可以的,因为赋值之前USER()函数返回的内容自动转换为latin1。至今,自动转换没有全部实施,但是以后的版本中应该工作正常。
尽管自动转换不属于SQL标准,SQL标准化文档中说每一个字符集是(根据支持的字符)Unicode的“子集”。因此,一个知名的原则是,“适用超集的字符集能够应用于其子集”,我们相信Unicode的校对规则能够应用于非Unicode字符串的比较。
注释:在MySQL5.1中,errmsg.txt文件全部使用UTF8。客户端字符集的转换是自动进行的,如同元数据。