各位好~小弟在学习mysql和php的时候,遇到几个字符集相关的问题,不能解决,还望好心人赐教。
Question1:
mysql的字符集参数:
| character_set_client     | utf8
| character_set_connection | utf8
| character_set_database   | utf8
| character_set_results    | utf8
| character_set_server     | utf8
| character_set_system     | utf8在这个情况下,我用cmd形式,
执行:mysql> insert into test values('我是中文');
会出现:ERROR 1406 (22001): Data too long for column 'text' at row 1
如果在这之前,先执行mysql> set names gbk,则可以成功插入值。
为什么会出现这种情况?如何才能做到在以上字符集参数的条件下不执行“set names gbk”也能正确插入中文?我个人认为是这样的:
cmd命令行下是用gbk编码的,即“我是中文”四个字在client端采用gbk编码;
因为character_set_client=utf8,所以在传向mysql时,mysql认为client端传入的字符串是utf8编码(其实是gbk编码);
然后因为character_set_connection=utf8,与character_set_client一样,在保存时就不转码,直接保存了下来;
最后在查询返回时,由于character_set_results=utf8,与character_set_connection一样,所以直接把保存的字符串不转码,直接作为utf8的编码返回;
这样,本来是gbk编码的字符串被cmd命令行当成了utf8的字符串显示,自然成了乱码!
在执行了“set names gbk”后,这三个参数都被改为了gbk,以gbk存,gbk传输,gbk显示,自然就是正确的了。Question2:
mysql的字符集参数和问题1一样,都是utf8;php文件编码为utf8;浏览器编码为utf8;
insert.php:
<?php 
    mysql_connect("localhost", "root", "admin") or die("数据库连接失败");
    mysql_select_db("aitaolun") or die("数据库选择失败");
    mysql_query("set names utf8");
    mysql_query("insert into test values('我是中文')");     
?>show.php:
<?php 
    mysql_connect("localhost", "root", "admin") or die("数据库连接失败");
    mysql_select_db("aitaolun") or die("数据库选择失败");    mysql_query("set names utf8");
    $query_result = mysql_query("select * from test");   
    while($test = mysql_fetch_array($query_result))
    {
        echo $test["text"]."<br/>";          
    }
?>
网页能正常显示“我是中文”,且数据库中显示“我是中文”;但是,去掉mysql_query("set names utf8")...........................................................
insert.php:
<?php 
    mysql_connect("localhost", "root", "admin") or die("数据库连接失败");
    mysql_select_db("aitaolun") or die("数据库选择失败");
    mysql_query("insert into test values('我是中文')");     
?>show.php:
<?php 
    mysql_connect("localhost", "root", "admin") or die("数据库连接失败");
    mysql_select_db("aitaolun") or die("数据库选择失败");
    $query_result = mysql_query("select * from test");   
    while($test = mysql_fetch_array($query_result))
    {
        echo $test["text"]."<br/>";          
    }
?>
网页能正常显示“我是中文”,且数据库中显示却是乱码。然后我在insert.php中加上“set names utf8”以告知mysql我将要传入utf8编码的字符串,然后查看数据库,确实存入了正确的字符串。由此可见,有两个可能:1.mysql使用的参数并不是我设置的(这个可能性不大,不然就是mysql的bug);2.我的php文件编码并不是显示给我的utf8(我用的zend studio,这个可能么?bug?)。
基于以上猜测,我又做了以下实验:insert.php中不执行“set names utf8”,而采用默认的方式插入;在show.php中执行
“set names xx_charset”,xx_charset枚举当前mysql所支持的所有的字符集,最后发现,当xx_charset=latin1的时候,显示的中文正确了!也就是说,我在zend studio下编写insert.php时,虽然使用了utf8的编码,但是在执行查询时,character_set_client=latin1............囧随后我查看了mysql的配置文件,发现
[mysql]
default-character-set=utf8
[mysqld]
default-character-set=utf8
且没有任何一个设置是latin1........
到这里,就不明白了,到底是什么导致了这种情况?mysql的bug?zend studio的bug?
还望高人解答,非常感谢:)

解决方案 »

  1.   


    新手表示这方面也不大明白,我都是用的gb2312,网页编码是,set names那个也是。。
    暂时一切正常等高人讲解学习。
      

  2.   

    安装Mysql的时候不都是选gb2312吗?
      

  3.   

    ok, 先说概念:
    | character_set_database | utf8
    | character_set_server | utf8
    | character_set_system | utf8
    这几个对一个mysql服务是一样的,但是
    | character_set_client 
    | character_set_connection 
    | character_set_results | utf8
    这几个是针对client端连接的, 所以在不同的client(不同连接)里看到的有可能不同如果你从mysql命令行工具看到这3个参数如此设置,只能说当时你的mysql工具是如此设置的, 不代表你的phpmyadmin是一样的,也不代表你的php程序是一样的,(当然它们也可以设成一样)set names xxx
    等价于
     set character_set_client = xxx;
     set character_set_connection = xxx;
     set character_set_results = xxx;问题1,
    为什么会出现这种情况? 
    A:下面你所写的你"个人认为"的部分完全正确
    如何才能做到在以上字符集参数的条件下不执行“set names gbk”也能正确插入中文?
    A:不能,你不告诉mysql是什么编码,它当然就当成是utf8的(根据设置)
    问题2,
    在不加set name的情况下, 
    你的php连接是用了latin1, 你可以在php里用SHOW VARIABLES LIKE 'CHARACTER%'看一下(和select一样)这个时候存入数据库的是错误的中文,一个3字节中文(utf8)会占用6个字节,why? 因为你的中文页面是utf8的,所以提交给mysql的是3字节,但是mysql以为是latin1编码,它视其为3个latin1字符(且都是高位字符),
    然后将其转为对应的utf8字符,(latin的高位字符在utf8里大都是2个字节),所以一共是6个字节,
    这点你可以在mysql里用select BIT_LENGTH(xxx)和CHAR_LENGTH(xx)看出来, 那么为什么在网页上是正确的中文...? 因为显示时,mysql又转换为原来的3个latin1高位字符,而这3个字符又被浏览器解释为2个正确的汉字...
    为什么在数据库显示为乱码,....我猜你是在phpmyadmin中看的?或其他数据库工具...都一样,因为他们都有相应的character set设置,应该是utf8,那么mysql就没有把它转成latin1的字符,而是转成了utf8(没动),所以你看到的是乱码下面你insert不加setname, 而show里加latin1,实际上是一样的...
    最后关于配置文件,我也还要再研究一下
    mysqld是服务端,无影响
    mysql可能是与mysql工具有关,你可以试试然后你加对应行到[client]节看看,是否对你的php程序有作用
    时间紧,没有举例,如果你需要我可以补上-----------------------------------------------------------如果愿意,欢迎加入我们的google wave group: 
    我正在想写一个关于mysql编码的step by step的解决方案,你也可以参加http://topic.csdn.net/u/20100205/23/8c4869ec-7ab3-4045-b22b-97c95d86e566.html
      

  4.   

    3Q~受教了,以前还不知道每个client都有自己的设置- -......那再土问下,我怎么在zend studio把这三个设置一劳永逸的改掉?