今天继续研究字符集.
上次似乎的出了结论,但是后来测试又发现一些怪现象,所以今天继续测试.就是关于客户端字符集的,因为每一个客户端都有自己的字符集,当其与设置的character_set_client以及character_set_results不匹配的时候,其中的转换关系是否如我所预期的呢?
我使用我机器上的windows命令行,因为我确定其客户端使用的字符集是gbk
Create database tim character set utf8;
Use tim;
Create table test_gbk(t varchar(100)) character set gbk;
Create table test_utf8(t varchar(100)) character set utf8;
insert test_gbk values('阳光'),('太阳'),('济南'),('光明');
insert test_utf8 values('阳光'),('太阳'),('济南'),('光明');
select * from test_gbk;
select * from test_utf8;
都能正常显示中文
Select length(t) from test_gbk; 4
Select length(t) from test_utf8; 6
Select char_length(t) from test_gbk; 2
Select length(t) from test_utf8; 2
也是正常的存储了对应的gbk编码以及utf8编码
Set character_set_connection=’ascii’;
奇怪的事情出现了
Select * from test_gbk; select * from test_utf8;
都能够正常显示中文,并没有如我预期的一样从gbk,utf8转换到ascii出现数据丢失.
但是insert into test_gbk values(‘中国’); insert into test_utf8 values(‘中国’);
Select * from test_gbk; select * from test_utf8;
我们刚插入的一行显示的是问号?
也就是说在insert的时候,是有一个character_set_client到character_set_connect然后再到数据库字符集的转换过程的,但是在select的时候,这个转化过程是没有的.
然后我们来看一下character_set_client与character_set_results起的作用
在一个utf8的客户端,set names gbk;
INSERT INTO test_gbk VALUES ('南方');
INSERT INTO test_utf8 VALUES ('南方');
然后在设置正常的命令行查看,得到的结果均是”���”
以LENGTH函数查看,前者得到的结果是6,后者得到结果是9.
我们分析一下过程,因为是utf8的客户端,所以实际得到的均是utf8编码的”南方”
然而因为我们set names gbk, 也就是说character_set_clients, character_results, character_connection均是gbk,client到connection不需要转换,存储到数据库的时候,当存储到test_gbk的时候,不需要转换,所以存储的是6个字节的utf8编码”南方”;
当存储到test_utf8的时候,执行从gbk到utf8的转换,所以引擎讲utf8编码的”南方”视为gbk编码的3个汉字, 也就是”���”,然后再以utf8编码来编码这3个汉字,所以就变成了9个字节.
我前面谈到过phpmyadmin的字符集,也曾经在phpmyadmin上set names,结果不起作用.
经研究,发现phpmyadmin在连接mysql数据库的时候,character set connection是可以设置的,就是通过选择MySQL connection collation来设置的,而character_set_client, character_set_results目前尚不清楚是怎样决定的,其客户端字符集则是跟登陆时候选择的语言所对应的php文件编码有关系.
我使用的phpmyadmin是3.2.4, 在phpmyadmin的library目录下有一个select_lang.lib.php的文件,其中定义了所有我们在登陆时候可以选择的语言列表:
return array(
'af-utf-8' => array('af|afrikaans', 'afrikaans-utf-8', 'af', ''),
'ar-utf-8' => array('ar|arabic', 'arabic-utf-8', 'ar', 'العربية'),
'az-utf-8' => array('az|azerbaijani', 'azerbaijani-utf-8', 'az', 'Azərbaycanca'),
'bn-utf-8' => array('bn|bangla', 'bangla-utf-8', 'bn', ''),
……
其中每一条都有类似于”afrikaans-utf-8”,”arabic-utf-8”,”azerbaijani-utf-8”,”bangla-utf-8”的字符串,phpmyadmin根据选择语言所对应的这一串字符串来寻找想对应的界面配置文件,这些文件存储在phpmyadmin的lang目录下,而这个文件中第一行定义的变量$charset则决定了登陆以后的页面字符集,也可以通过查看页面源码文件中的字符集来查看.