MySQL 乱码问题终极揭秘

hehe,在标题党横行的年代,不搞一个耸人听闻的标题就不能引人瞩目。不过,就我个人经验看,对这个问题搞个“终极揭秘”倒也不是什么难事儿 :)

 

MySQL 的乱码问题,大概是系统开发起步时出现频率最高的问题了。见招拆招(有时是以错对错)的话,面上总是能解决问题,但隐患不除,没准什么时候又冒出来;有人给出简单彻底的方案:所有库表都用 UTF-8 编码,本该天下太平了,但有时候还是出问题。

 

这个问题真的那么复杂吗?怎么就那么难以驯服呢?其实,问题远比想象的简单得多!

 

关键是要看穿一点:问题不出在数据库、表的编码方式上,只要弄好“连接”的编码方式就 OK 了。

 

·连接的编码方式

 

MySQL 足够聪明,只要你跟它说话时发音准确,它就会很好地执行命令,而你完全不用关心它的内部存储方式这种细节。

所以,你只需做好两件事:

 

1. 明确地告诉 MySQL 你将在 SQL 语句中使用何种编码方式;

 

2. 在发送 SQL 语句时,准确地使用前面声明的编码方式。

 

为了做到第一点,最简单的办法就是在建立了数据库连接后,不管三七二十一,先执行一个 "SET NAMES ..." 再说。

 

至于第二点,就跟具体的编程语言有关系了。对于 PHP 语言,“字符串”作为一个值,本身就是一个按某种编码方式组织的“字节串”,如果不符合要求的话可以用 iconv() 做转换。对于 Java 语言来说,因为书写 SQL 语句的 String 本身一定是 UCS2 编码的,你可以用连接串里的 useUnicode 和 characterEncoding 来告诉 Driver 把语句中的字符串值转换成何种编码方式,或者自己先把 String 转换成特定编码方式的 byte[] 后再用 setBytes()、setBinaryStream() 等方式传递给 PreparedStatement。

 

只要做好上面两点,包你不会再遇到 MySQL 乱码问题。当然,对于整个系统而言,还有其它环节可能产生乱码,比如网页编码,只要细心分辨,都不难解决。

 

·数据库表的编码方式

 

上面我们看到,要让 MySQL 不出现乱码,要点是在于数据库连接的编码方式,而数据库表的编码方式并不重要,MySQL 会自动做好编码转换工作。

 

那么在做数据库设计的时候,怎么选择编码方式呢?其实这时候考虑的应该是另外几个因素,比如:

 

1. 字符集的兼容性。如果预期将在一个字段中同时保存简体、繁体、日文等字符,那你就必须选择一个能同时容纳这几种字符集的编码方式,一般来说,UTF-8 是最好的选择。

 

2. 存储效率。如果预期仅保存简体中文,那么选择 GBK 会比 UTF-8 的存储效率高一些。不过,似乎大多数情况下,这一因素并不很重要。

 

3. 结合实际的应用情况,尽量减少数据库访问过程中的编码转换环节。如下图所示的传输过程,其中“C转换”是客户端的转换工作(可能是应用程序负责,也可能是 Driver 负责,比如 JDBC Driver),“S转换”是服务端的编码转换(由 MySQL 自动进行)。


客户端程序 ------------> 客户端接口 ----------> 服务端接口 --------------> 数据库存储
 UCS2/GBK/…  C转换        编码传输         S转换   UTF-8/GBK/…

客户端程序 <------------ 客户端接口 <---------- 服务端接口 <------------ 数据库存储
 UCS2/GBK/…  C转换        编码传输         S转换   UTF-8/GBK/…

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值