一直以   来只知道 mysql_query("S   ET NAMES UTF8");    是设定数据库编码的,但是一直不清楚“SET NAMES UTF8”到底是什么。直到今天才知道 SET NAMES xxx 也是 mysql 语句。 

     真的感觉到自己的功课还没做到家,现有知识储备比较匮乏。现将所查相关资料记下: 

1、SET NAMES ‘charset_name’  

SET NAMES xxx 用于显式设置客户端之后发送的 SQL 语句使用什么字符集。因此,SET NAMES 'cp1251' 语句告诉服务器将来从这个客户端传来的信息采用字符集 cp1251 。同时它还为服务器发送回客户端的结果指定了该字符集。(例如,当你执行 SELECT 语句,列值以你指定的字符集显式) 


2、连接字符集和校对  

(1) 一些字符集和校对规则系统变量与客户端和服务器的交互有关。 

  • 服务器字符集和校对规则对应 character_set_server 和 collation_server 变量的值。
  • 默认数据库字符集和校对规则对应 character_set_database 和 collation_database 变量的值。

在客户端和服务器的连接处理中,也涉及了字符集和校对规则变量。 

每一个客户端有一个连接相关的字符集和校对规则变量。 



(2)什么是“连接

 


客户端

  通过“连接”发送 SQL 语句到服务器   ,例如查询。服务器通过连接发送响应给客户端,例如结果集。 

对于客户端连接,相关的为连接的字符集和校对规则的问题,这些问题均能够通过系统变量来解决。

 


(3) 当查询离开客户端后,在查询中使用哪种字符集? 



服务器使用 character_set_client 变量作为客户端发送的查询中使用的字符集。 



(4) 服务器接收到查询后如何转换字符集? 



转换时,服务器使用 character_set_connection 和 collation_connection 系统变量。它将客户端发送的查询从 character_set_client 系统变量指定的字符集转换到 character_set_connection 指定的字符集(除非字符串文字具有象 _latin1 或 _utf8 的引介词)。collation_connection 对于字符串比较是有用的。但对于列值字符串比较不起作用,因为会采用更高的优先级校对规则。 



(5)服务器发送结果集或返回错误信息到客户端之前应该转换为哪种字符集? 



character_set_results 变量指示服务器返回查询结果到客户端使用的字符集。包括结果数据,例如列值和结果元数据(如列名)。



=========================================

两外一篇文章中的部分内容如下:(摘录+个人总结)


如果在 mysql 配置文件中不对字符编码进行设置或者按照如下设置






[mysql]           


          default-character-          set          =utf8              //          客户端的默认字符集         


                    


          [mysqld]         


          default-character-          set          =utf8              //          服务器端默认的字符集



则在 mysql 中可以查看到如下信息:



mysql> show variables           like          'character_set_%'          ;         


          +          --------------------------+----------------------------------+         


          | Variable_name            | Value                            |         


          +          --------------------------+----------------------------------+         


          | character_set_client     | latin1                           |         


          | character_set_connection | latin1                           |         


          | character_set_database   | utf8                             |         


          | character_set_filesystem |           binary                                    |         


          | character_set_results    | latin1                           |         


          | character_set_server     | utf8                             |         


          | character_set_system     | utf8                             |         


          | character_sets_dir       | /usr/          local          /mysql/share/charsets/ |         


          +          --------------------------+----------------------------------+         


          8           rows          in          set          (0.00 sec)         


                    


          mysql>



此时若通过程序从数据库里按照UTF-8编码方式读取数据,很有可能是一串“?????”或者是其他乱码。



解决办法是,在连接数据库之后且读取数据之前,先执行 SET NAMES UTF8 命令。
在 mysql 命令行中执行 SET NAMES UTF8; 后重新查看字符编码信息,结果如下:





mysql>           set          names utf8;         


          Query OK, 0           rows          affected (0.00 sec)         


                    


          mysql>          


          mysql> show variables           like          'character_set_%'          ;         


          +          --------------------------+----------------------------------+         


          | Variable_name            | Value                            |         


          +          --------------------------+----------------------------------+         


          | character_set_client     | utf8                             |         


          | character_set_connection | utf8                             |         


          | character_set_database   | utf8                             |         


          | character_set_filesystem |           binary                                    |         


          | character_set_results    | utf8                             |         


          | character_set_server     | utf8                             |         


          | character_set_system     | utf8                             |         


          | character_sets_dir       | /usr/          local          /mysql/share/charsets/ |         


          +          --------------------------+----------------------------------+         


          8           rows          in          set          (0.00 sec)         


                    


          mysql>




可以看到发生变化的变量为

  • character_set_client
  • character_set_connection
  • character_set_results

手册上说,上面那句 SET NAMES UTF8; 作用相当于: 



SET          character_set_client = utf8;         


          SET          character_set_results = utf8;         


          SET          character_set_connection = utf8;


而这 3 个变量正对应了编码转换  路径   中的3个部分: 

  • 信息输入路径:client→connection→server
  • 信息输出路径:server→connection→results

换句话说,在每个路径上信息都要经过3次字符集编码转换。 

所以,在两种字符集不兼容的情况下,如果进行了相应的转换,则会出现乱码。


注:



  1. SET NAMES UTF8 的作用只是临时的,mysql 重启后就恢复默认了。
  2. 设置字符编码的时候使用的是 utf8 并非 utf-8 。