② 第二种方式
假如说连接器(connection)的字符集是GBk,这个过程又该是怎么进行的呢,下面我们仍然进行文字说明。
首先,在客户端输入的字符,使用的字符集是GBK。当经过连接器的时候,连接器发现客户端发送过来的字符的字符集,与自身字符集相同,因此顺利通过了连接器。
接着,当字符通过连接器发送给mysql服务器进行存储的时候,发现mysql服务器的字符集是UTF8,与自身的字符集GBK并不一致。因此,连接器此时又会进行"字符集的自动转换",将该字符(以GBK进行编码)转换为以UTF8格式的编码,进行显示,转换完成以后,再次发送给mysql服务器,进行最终的存储。
“当我们从mysql服务器查数据的时候,返回过程又是怎么进行的呢?”
首先 ,mysql服务器会将结果以UTF8编码格式进行返回,通过连接器的时候,连接器发现mysql服务器的字符集,与自身的字符集并不一致,于是连接器会进行"字符集的自动转换",将返回的结果(以UTF8进行编码)转换为以GBK格式的编码,进行显示。接着连接器又将转换后的结果,准备发送给客户端,此时发现客户端的字符集,与自身的字符集一致。因此直接发送给客户端,成功在CMD窗口中显示。
5、上述两种图示法的实际操作演示
1)先了解如下几个代码
1)设置客户端的字符集 set character_set_client=gbk; 2)设置连接器的字符集 set character_set_connection=utf8; 3)设置返回结果的字符集 set character_set_results=gbk;
2)代码演示过程如下
mysql> desc student; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | sid | int(11) | NO | PRI | NULL | auto_increment | | sname | varchar(20) | NO | | NULL | | | age | int(11) | YES | | NULL | | +-------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> select * from student; +-----+-------+------+ | sid | sname | age | +-----+-------+------+ | 1 | 张三 | 23 | | 2 | 李四 | 25 | | 3 | 王五 | 43 | | 4 | 赵六 | 34 | +-----+-------+------+ 4 rows in set (0.00 sec) mysql> #要想不乱码,需要指定客户端的编码,让连接器不理解错误。 mysql> #这样就不会存入错误数据。 mysql> #往回取数据的时候,还要告诉连接器,如果你从服务器返回,你应该给我转成什么格式。 mysql> #因此,一共需要设置3个参数: mysql> #1、客户端发送的编码; mysql> #2、连接器使用的编码; mysql> #3、返回数据的编码; mysql> mysql> mysql> mysql> #当前的情况是:客户端是GBK,服务器最终存储的是UTF8。 mysql> #因此,你就要明确告诉服务器,我的客户端是GBK的。 mysql> #命令如下: mysql> set character_set_client=gbk; Query OK, 0 rows affected (0.00 sec) mysql> #再告诉连接器,使用UTF8。 mysql> #命令如下: mysql> set character_set_connection=utf8; Query OK, 0 rows affected (0.00 sec) mysql> #再告诉,如果你返回值给我看的话,也请返回GBK。 mysql> #命令如下: mysql> set character_set_results=gbk; Query OK, 0 rows affected (0.00 sec) mysql> insert into student(sname,age) values ("编码不乱",22); Query OK, 1 row affected (0.10 sec) mysql> select * from student; +-----+----------+------+ | sid | sname | age | +-----+----------+------+ | 1 | 张三 | 23 | | 2 | 李四 | 25 | | 3 | 王五 | 43 | | 4 | 赵六 | 34 | | 6 | 编码不乱 | 22 | +-----+----------+------+ 5 rows in set (0.00 sec) mysql> #我的客户端是GBK,但是我偏要骗对方,是UTF8。 mysql> set character_set_client=utf8; Query OK, 0 rows affected (0.00 sec) mysql> insert into student(sname,age) values ("编码乱不乱?",22); ERROR 1366 (HY000): Incorrect string value: '\xB1\xE0\xC2\xEB\xC2\xD2...' for column 'sname' at row 1 mysql> #此时,"编码乱不乱?"对应的GBK的内码,转换成UTF8,压根就出错,不允许插入。 mysql> set character_set_client=gbk; Query OK, 0 rows affected (0.00 sec) mysql> #我偏要对方返回给我的数据是UTF8。 mysql> set character_set_results=utf8; Query OK, 0 rows affected (0.00 sec) mysql> select * from student; +-----+--------------+------+ | sid | sname | age | +-----+--------------+------+ | 1 | 寮犱笁 | 23 | | 2 | 鏉庡洓 | 25 | | 3 | 鐜嬩簲 | 43 | | 4 | 璧靛叚 | 34 | | 6 | 缂栫爜涓嶄贡 | 22 | +-----+--------------+------+ 5 rows in set (0.00 sec) mysql> #此时,请问我再插入数据。 mysql> insert into student(sname,age) values ("编码乱不乱?",22); Query OK, 1 row affected (0.09 sec) mysql> select * from student; +-----+--------------------+------+ | sid | sname | age | +-----+--------------------+------+ | 1 | 寮犱笁 | 23 | | 2 | 鏉庡洓 | 25 | | 3 | 鐜嬩簲 | 43 | | 4 | 璧靛叚 | 34 | | 6 | 缂栫爜涓嶄贡 | 22 | | 7 | 缂栫爜涔变笉涔憋紵 | 22 | +-----+--------------------+------+ 6 rows in set (0.00 sec) mysql> #虽然插入返回的数据仍然是乱码,但是属于的是,编码和解码不一致导致的乱码,可以修复。 mysql> set character_set_results=gbk; Query OK, 0 rows affected (0.00 sec) mysql> select * from student; +-----+--------------+------+ | sid | sname | age | +-----+--------------+------+ | 1 | 张三 | 23 | | 2 | 李四 | 25 | | 3 | 王五 | 43 | | 4 | 赵六 | 34 | | 6 | 编码不乱 | 22 | | 7 | 编码乱不乱? | 22 | +-----+--------------+------+ 6 rows in set (0.00 sec) mysql> #再看另外一种情况: mysql> #声明客户端是GBK; mysql> set character_set_client=gbk; Query OK, 0 rows affected (0.00 sec) mysql> #声明连接器是GBK; mysql> set character_set_connection=gbk; Query OK, 0 rows affected (0.00 sec) mysql> #声明返回值是GBK; mysql> set character_set_results=gbk; Query OK, 0 rows affected (0.00 sec) mysql> #如上操作,插入中文,会不会乱码? mysql> insert into student(sname,age) values ("真不乱?",666); Query OK, 1 row affected (0.07 sec) mysql> select * from student; +-----+--------------+------+ | sid | sname | age | +-----+--------------+------+ | 1 | 张三 | 23 | | 2 | 李四 | 25 | | 3 | 王五 | 43 | | 4 | 赵六 | 34 | | 6 | 编码不乱 | 22 | | 7 | 编码乱不乱? | 22 | | 8 | 真不乱? | 666 | +-----+--------------+------+ 7 rows in set (0.00 sec) mysql> #现在,我偏偏声明连接器的字符集是latin1。 mysql> set character_set_connection=latin1; Query OK, 0 rows affected (0.00 sec) mysql> insert into student(sname,age) values ("还不乱?",888); Query OK, 1 row affected, 1 warning (0.32 sec) mysql> select * from student; +-----+--------------+------+ | sid | sname | age | +-----+--------------+------+ | 1 | 张三 | 23 | | 2 | 李四 | 25 | | 3 | 王五 | 43 | | 4 | 赵六 | 34 | | 6 | 编码不乱 | 22 | | 7 | 编码乱不乱? | 22 | | 8 | 真不乱? | 666 | | 9 | ???? | 888 | +-----+--------------+------+ 8 rows in set (0.00 sec) mysql> #这次乱码,是因为latin1容量小,gbkt容量大。这个转换就像大鱼过小鱼网一样,丢了块肉。 mysql> #也就是说,大容量转换为小容量时,会丢失字节。 mysql> #思考一下:这次乱码能否修复? mysql> #不能。。。 mysql> #因此,记住这个原则: mysql> #字符集,服务器>=连接器>=客户端。 mysql> #也即:进行字符集的转换的时候,必须是小容量转换为大容量(小鱼过大鱼网)d,才不会丢失字节。 mysql> ######################################### mysql> #再回头看:一个比较巧的地方。 mysql> #client、connection、server字符集设置的都是GBK,不会导致乱码。 mysql> #如果三者都是GBK,可以简写成如下形式: mysql> #set names gbk; mysql> #这一句话,其实表示了3句话的含义。 mysql> Terminal close -- exit!