新产品开发,有时候需要迁移历史数据,而且往往还是异构系统的数据。
这时候常常会遇到乱码的问题,原因主要是因为字符集不匹配引起的。
对于MySQL而言,存在客户端字符集、服务器字符集、数据库字符集以及连接字符集等变量,
要查询这些设置,可在MySQL命令行下执行如下语句:
SHOW VARIABLES LIKE 'character_set_%';
SHOW VARIABLES LIKE 'collation%';
下面把MySQL字符集相关的基础知识从MySQL Manual在线文档翻译如下:
10.1.4. 连接字符集和整理
有一些字符集和整理变量是和客户端服务器之间的交互相关的:
服务器端的字符集和整理分别是 character_set_server和collation_server系统变量
数据库的字符集和整理分别是character_set_database和collation_database系统变量
还有其他的字符集和整理系统变量也被使用在客户端服务器之间的连接数据交互上。每个客户端都有自己的字符集和整理系统变量。
客户端通过连接发送SQL语句,比如查询,服务器返回结果集或者错误信息,这就引出了和连接的字符集和整理处理相关的若干问题,
这些问题的回答都涉及到系统变量:
Q:客户端发送的语句是什么字符集?
A:服务器把character_set_client认为是客户端传递过来的语句的字符集
Q:服务器接收到语句后应该转换成什么样的字符集?
A:character_set_connection和collation_connection,服务器把语句从character_set_client转换为character_set_connection (除了那些字符串中包含介绍如_latin1或_utf8).
collation_connection对字符串的比较很重要,但对于比较查询字符串和列数据没有作用,因为列有它们自己的整理,具有较高的优先排序。
Q:在返回结果给客户端前,服务器应该把结果转换成什么样的字符集?
A:character_set_results系统变量指明了返回结果集的字符集。这包含结果数据如列数据以及元数据如列名称。
客户端可以微调这些变量, 或者使用默认值。
如果不使用默认值,你必须更改所有和服务器的连接的字符集设置。
有两个语句会影响连接相关的所有字符集变量:
SET NAMES 'charset_name' [COLLATE 'collation_name']
SET NAMES 指明客户端以什么字符集发送SQL语句给服务器。
因此, SET NAMES 'utf8' 告诉服务器, “后续的客户端语句字符集都是utf8编码的”
它还指定了服务器也应该以这个字符集返回结果给客户端。(比如, 它指明当你使用SELECT语句的时候,以什么样的字符集返回列数据)
SET NAMES 'x' 语句等同于如下这些语句:
SET character_set_client = x;
SET character_set_results = x;
SET character_set_connection = x;
设置character_set_connection为x同时也隐式的把collation_connection设置为x的缺省整理(collation).
不需要显式的设定该collation. 为了指定一个特别的collation, 可以使用可选COLLATE语句:
SET NAMES 'charset_name' COLLATE 'collation_name'
SET CHARACTER SET charset_name
SET CHARACTER SET和SET NAMES相似,但除了设置character_set_connection和collation_connection外还同时设置了数据库字符集character_set_database和collation_database.
SET CHARACTER SET x 语句等同于同时执行下面3条语句:
SET character_set_client = x;
SET character_set_results = x;
SET collation_connection = @@collation_database;
设置collation_connection为x同时也隐式的把character_set_connection设置为和x关联的字符集(等同于执行SET character_set_connection = @@character_set_database).
不需要显式的设定character_set_connection.
注意:
ucs2 不能被用作一个客户端的字符集, 这意味着它不能被SET NAMES或SET CHARACTER SET语句所使用.
当一个客户端连接到服务器的时候,客户端发送它想使用的字符集名称,服务器使用这个名称设置character_set_client, character_set_results以及character_set_connection系统变量.
效果上等同于, 服务器执行了一个SET NAMES操作。
例子: 假设column1定义为CHAR(5) CHARACTER SET latin2. 如果你没有设置SET NAMES或者SET CHARACTER SET, 那么对于SELECT column1 FROM t这条语句,
服务器将以客户端连接时所用的字符集返回column1的数据。
另一方面,如果你在执行SELECT语句之前执行了SET NAMES 'latin1' 或 SET CHARACTER SET latin1, 那么服务器将把latin2的数据转换为latin1然后返回.
如果字符集不完全匹配的话,转换可能会产生数据丢失和乱码。
如果你不希望服务器做任何的结果转换,那么可以把character_set_results设置为NULL:
SET character_set_results = NULL;
你还必须考虑MySQL应用程序执行时的环境. 参看章节10.1.5, “Configuring the Character Set and Collation for Applications”.
更多关于错误码的字符集,参看章节10.1.6, “Character Set for Error Messages”.
原文链接如下:
http://dev.mysql.com/doc/refman/5.0/en/charset-connection.html
iefreer