对于语言编码,MySQL都为我们做了什么

xuzuning 2010-08-06 04:32:12
经常有朋友问到 mysql 的乱码问题。得到的答案多半是说:要保证编码一致,甚至php程序文件也要做到编码一致。

其实不然!

背景:
我还是在 mysql4 时代使用过 mysql,他没有编码问题,但也没有存储过程。所以就改用 sql server 了。最近因项目需求,又把 mysql 捡起来了。也测试了一下 mysql 的语言编码问题
我安装的是 mysql 5.1.47 版本,安装时选则了 utf8 作为默认语言
但我仍然喜欢使用 gbk 编码,因为编辑 utf-8 编码的文件需要用编程工具,而我只喜欢用 记事本

于是我在上述环境中以 DEFAULT CHARSET=gbk 建库建表
并在 mysql_query('set names gbk'); 之后进行数据库操作。一直如此,并无任何问题。

后来有一个必须为 utf-8 编码的页面,他还要使用那个 gbk 编码的库中的数据。怎么办呢?直接的想法就是取出数据后再用 iconv 函数转码。很是费劲吧?

其实 mysql 已经做的很好了,只需要设置一下语言
mysql_query('set names utf8');
于是查询结果都是 utf-8 编码的了
不错!
于是我向 gbk 编码的表中插入 utf-8 编码的数据,然后用 gbk 编码读回(set names gbk)
真不错!
刚才插入的数据已然以 gbk 编码展示,一点乱码也没有


请有兴趣的朋友发表高论!
谢绝顶贴!

...全文
438 点赞 收藏 51
写回复
51 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
ruanchao 2010-08-10
看似基础性的问题,如果不知其所以然,也会被搞迷糊的。

赞一个
回复
yhr7289864 2010-08-10
<?php
header("Content-type:text/html;Charset=UTF-8;");
$link=mysql_connect("localhost","root","123456") or die("无法连接服务!");
mysql_select_db("codegbk",$link) or die("数据库无法选择");
mysql_query("set names utf8");
$rs = mysql_query("select *from user",$link);

$sql = "insert into user values(default,'测试乱码')";
mysql_query($sql);
while($row = mysql_fetch_array($rs)){
echo $row["username"]."<br/>";
}
?>

经过几次乱码的测试,只要在插入数据时候 set names 这个编码与页面的编码统一,而与数据库的编码无关系。在读数据的时候set names 这个编码与页面编码统一,也就相当与 set names 是告诉mysql 我要读取和存储什么样的编码数据。现在页面一直未出现问题.
回复
wll474127597 2010-08-09
我还以为是什么高深的技术诶!
回复
wll474127597 2010-08-09
汗,做PHP的谁不知道这个,居然跑论坛来发这个!
回复
vov123 2010-08-09
我从数据库输出的时候是
$con=@mysql_connect("localhost","root","123") or die("数据库无法连接");
$db=@mysql_select_db("my") or die("库无法连接");
header("Content-Type:text/html;charset=utf-8");
执行updata 语句的时候是
$con=@mysql_connect("localhost","root","123") or die("数据库无法连接");
$db=@mysql_select_db("my") or die("库无法连接");
mysql_query("set names GB2312");
这样不会有乱码 可是要是同一个网页同时执行这两个操作就乱了。。。。怎么办?都说要统一编码 可是怎么把所有的编码都设置统一啊
回复
c461439564 2010-08-09
语言混编就没弄过了,统一编码是正道,其它的申明执行命令过于麻烦、易出问题
回复
LKK 2010-08-09
学习来了。。
回复
helloyou0 2010-08-08
唠叨, 27楼, 38楼说的都是对的。

mysql的转换过程就是
存入时:character_set_client =〉
character_set_connection =〉
character_set_database(table/column )

取出时:character_set_database(table/column ) =〉
character_set_connection =〉
character_set_results

这个转换中,字符集必须相容(能一一对应当然最好),如果有latin1这样字符数很少的字符集,转换后必然会有字符丢失。

我以前回复的帖子里有解释得更详细的,可以搜索到。




回复
Dleno 2010-08-08
[Quote=引用 33 楼 quzhongxiong 的回复:]

前段时间我也发现一个非常奇怪的问题,就是MYSQL用的都是UTF8,页面用的也是UTF8,但为了避免乱码的问题,我还是加上了set names 'utf-8',这下问题就来了,乱码,百思不得其解,编码都是一样的,为什么会乱码呢,搞了好久,于是死马当活马医,把set names 'utf-8'改成set names 'utf8',怪了,又好了,所以顺便也想问一下各位,难道"utf8"与"utf-8……
[/Quote]

mysql里只有utf8,没有utf-8的编码名字
回复
foolbirdflyfirst 2010-08-08
set names utf8有3个过程
---------------------------------------------
set character_set_client utf8; #通知mysql,客户端发送的是utf-8编码数据
set character_set_connection utf8 ;#客户端编码与存储引擎连接校对
set character_set_results utf8 ; #从存储引擎得到的数据转成utf8返回给客户端

mysql帮我们完成了转换过程,不管是客户端gbk访问utf-8数据库,还是utf-8客户端访问gbk数据库,都没问题。
统一编码是为了系统的多语言性,移植性。
gbk的页面读其它语言的数据就肯定错了。
gbk要成为世界标准,最起码先得支持世界各国文字,编码区得扩充到和unicode一样。
回复
pak001 2010-08-08
本人用phpmyadmin经常乱码,不知道是不是mysql的问题
回复
steptodream 2010-08-08
最烦乱码问题了
全世界统一使用英文 统一编码就好了
回复
xuzuning 2010-08-08
[Quote=引用 35 楼 coolesting 的回复:]
假如,有一天,你的数据库要和别的应用程序共享数据,
那程序默认了utf-8,当调用你的数据时发现是gbk怎么办?

那么,默认情况下该程序就可能不正常显示你的数据了,
好比,你做好的作品给用户,而这些用户通常是白痴(对于计算机来说),
他们不懂设置这个那个,甚至也是根本看不明白后台管理的术语。



下面举两个例子:

再假设,我写程序时,都标了英文注解(utf-8),
……
[/Quote]
[Quote=引用 36 楼 coolesting 的回复:]
你可以用任何编码,只要mysql支持的,
关键你用这种编码存储时,当调用那一方也要支持,

但调用的程序目前可能是自己,但当别人来调用时,
别人也是否支持这种编码格式的数据呢?


我想这个原理大概和Web Service一样,如果不用统一的协议,很难说是什么结论。
[/Quote]

也正是这个原因,所以你用你的 utf-8 程序访问我的 gbk 数据库时只要声明一下 set names utf8 ,于是我的数据库就以 utf-8 编码向你提供数据;而我的 gbk 程序要从你的 utf8 数据库得到数据,也只需通知你的数据库 set names gbk 我需要 gbk 编码的数据

如果仅仅是为了所谓的“统一”,那么为什么不统一到 gbk 下呢?你如何知道中国标准不会成为世界标准呢
回复
quzhongxiong 2010-08-07
前段时间我也发现一个非常奇怪的问题,就是MYSQL用的都是UTF8,页面用的也是UTF8,但为了避免乱码的问题,我还是加上了set names 'utf-8',这下问题就来了,乱码,百思不得其解,编码都是一样的,为什么会乱码呢,搞了好久,于是死马当活马医,把set names 'utf-8'改成set names 'utf8',怪了,又好了,所以顺便也想问一下各位,难道"utf8"与"utf-8"这两种不同的写法造成的处理方式还会不同??
回复
xuzuning 2010-08-07
这是测试例
mysql_connect();
mysql_select_db('test');
mysql_query('DROP TABLE IF EXISTS `mb`);
$sql = <<< SQL
CREATE TABLE `mb` (
`ch` varchar(10) NOT NULL,
`val` varchar(50) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=gbk;
SQL;
mysql_query($sql);

function save($charset, $text) {
mysql_query("set names $charset");
mysql_query("insert into mb values ('$charset', '$text')");
}

function load($charset) {
mysql_query("set names $charset") or die(mysql_error());
$rs = mysql_query('select * from mb');
while($row = mysql_fetch_assoc($rs)) {
list($hex) = unpack('H*0', $row[val]);
echo "$charset $row[ch] : $row[val] $hex<br>";
}
}

$s = "漢字";

save('gbk', $s);
save('utf8', iconv('gbk', 'utf-8', $s));
save('big5', iconv('gbk', 'big5', $s));

load('gbk');
load('utf8');
load('big5');
回复
xuzuning 2010-08-07
[Quote=引用 28 楼 piger920 的回复:]
涉及3种编码的话 有问题 (测试是 表为latin1 插入gbk 读出utf8)
[/Quote]
latin1 是单字节编码,估计有点问题。

不过 php168 在安装时建议编码是 latin1
对于这个有何高论?!

回复
chenyuzou 2010-08-07
同意楼主的观点,mysql表中的内容以gbk还是utf8格式存储的并不重要,重要的是当我们从mysql中存取数据时要告诉mysql我们使用的是什么编码。也就是设置好set names 编码

另外附个网上找来的以十六进制查看字符串的函数:

function binhex($str) {
$hex = "";
$i = 0;
do {
$hex .= sprintf("%02x", ord($str{$i}));
$i++;
}
while ($i < strlen($str));
return $hex;
}
回复
骄傲青蛙 2010-08-07
你可以用任何编码,只要mysql支持的,
关键你用这种编码存储时,当调用那一方也要支持,

但调用的程序目前可能是自己,但当别人来调用时,
别人也是否支持这种编码格式的数据呢?


我想这个原理大概和Web Service一样,如果不用统一的协议,很难说是什么结论。
回复
骄傲青蛙 2010-08-07
假如,有一天,你的数据库要和别的应用程序共享数据,
那程序默认了utf-8,当调用你的数据时发现是gbk怎么办?

那么,默认情况下该程序就可能不正常显示你的数据了,
好比,你做好的作品给用户,而这些用户通常是白痴(对于计算机来说),
他们不懂设置这个那个,甚至也是根本看不明白后台管理的术语。



下面举两个例子:

再假设,我写程序时,都标了英文注解(utf-8),
当我有天心血来潮时突然要发布到sourceforge或code.google,
如果当时我用中文注解(gbk),那岂不是又要重新一次?

其实,平时我们尽都可以说家乡话(gbk),但为什么还要说普通话(utf-8)来交流,
但习惯了家乡话的人上网时会说一些别人看不明的术语。



人类有人类的语言,机械有机械的语言,我们选择统一的语言是为了更好的交流,
但这个统一需要平时的习惯来作支撑。


------ 卑人浅见,多谢指教
回复
无天 2010-08-06
mark,楼主这方法倒不错。
回复
发动态
发帖子
基础编程
创建于2007-09-28

2.1w+

社区成员

从PHP安装配置,PHP入门,PHP基础到PHP应用
申请成为版主
社区公告
暂无公告