继续mysql中的charset

继续折腾mysql的charset。又发现数据库安装到客户的机器上之后,某几个表INSERT一行数据的时候存入的汉字都是’?’,但UPDATE的时候又可以修改为正确的汉字。差别是,这几张表的INSERT数据是用存储过程做的,但UPATE是直接在PHP语句做的,而且PHP里面使用了”SET NAMES ‘utf8′”. 基本认为是存储过程的问题。网上查了资料,http://unix-cd.com/vc/www/26/2007-06/2948.html提到了:

由于存储过程中定义参数时,无法定义其字符集,因此调用存储过程的时候,会默认读取全局变量character_set_server,而且还是只读取mysqld启动时该全局变量的值作为存储过程中默认的传输字符集。因此,如果数据表/字段使用系统默认的字符集(比如utf8)的话,调用存储过程更新一些非英文的字符串字段时,就不会发生问题;但是,如果数据表/字段的字符集不是系统默认的字符集(比如默认是utf8,数据表使用的是 utf8),就会出现问题了。解决办法是:在my.cnf(windows下是my.ini),增加一行:

default-character-set=utf8

或者

character-set-server=utf8

也可以。如果只是在mysqld启动之后,在 mysql 命令行中用 SET 语法来更新的话则不起作用。

看到,客户机器上他们自己安装的MySQL服务器缺省字符集是utf8,因此问题基本明确。但加入default-character-set=utf8后,仍然不起作用。又做了一些试验的结果发现,新建一个数据库,同样的存储过程就可以了。最后发现虽然数据表设置了’utf8’的字符集,但原来创建数据库的时候,由于没有指定字符集,因此使用了默认的字符集,也是utf8了。好象存储过程并不是完全跟着character_set_server走,而是跟着所属数据库的字符集走。把数据导出,再导入新建的数据库,问题解决。

没有测试过,当character_set_server为utf8,而数据库建的时候用了utf8的话,还会不会出这个问题,测试一下,就应该知道到底存储过程到底受谁的影响,或者是两者都受。

当数据库是utf8的时候,为什么UPDATE后汉字是正确的呢?我猜测可能的解释:
1. 对于一般SQL语句:UTF8的数据来到服务器之后,因为表设置为UTF8,因此会存储utf8的内容,没有问题。
2. 对于存储过程:UTF8的数据来到服务器之后,因为数据库设置为utf8, 因此会做一次转换,转成utf8的数据,进入存储过程,然后实际插入的时候,由于表为UTF8的,那么再转换成UTF8的,然后插入。汉字在转换为utf8的这一步变成了’?’。

发表评论

电子邮件地址不会被公开。 必填项已用*标注