MySQL编码详解及中文乱码问题解决方案

3/7/2017来源:SQL技巧人气:1668

最近,在项目组使用的MySQL数据库中,插入数据出现乱码问题,出现诸如???,或者Ñ¡Ôñ等字符。为了防止在

今后项目中再次出现相类似问题。在这里对于MySQL编码问题做一个详细的介绍并对于乱码问题提出一些解决方案。

一. 概念介绍 1.字符集(Character set)

    字符集是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见的字符集名称:ASCII字符集、

GB2312字符集、BIG5字符集等。对于中文文字来说,数目大,而且还分为简体中文和繁体中文两种不同书写规范的文

字,故一般出现乱码都出现在输入中文数据的时候。常见的中文字符集:GB2312、GBK、UTF8等。

2.常见中文字符集介绍

GB2312:1980年发布,是中文信息处理的国际标准,在大陆及海外使用简体中文的地区是强制使用的唯一中

文编码。GB2312共收录6763个简体汉字、682个符号。

GBK:汉字国际扩展码,基本上采用了原来GB2312所有的汉字及码位,并涵盖原Unicode中所有的汉字,总

共收录了883个符号,21003个汉字及提供了1894个造字码位。GBK兼容GB2312,并且简、繁体字融于一库。

UTF8:UTF8编码包含全世界所有国家需要用到的字符,可在各国各种支持UTF8字符集的浏览器上显示,即使用UTF8编码,可在同一页面中显示多种国家的文字。

3.字符序(Collation)

     字符序是指在同一字符集内字符之间的比较规则,在确定字符序后,才能在一个字符集上定义什么是等价的字符,以及字符之间的大小关系。每个字符序唯一对应一种字符集,但一个字符集可以对应多种字符序,其中有一个是默认字符序(Default Collation). MySQL中的字符序名称遵从命名惯例:以字符序对应的字符集名称开头:以_ci结尾的表示大小写不敏感、以_cs结尾的表示大小写敏感,以_bin结尾的表示按编码值比较。例如:在字符序“utf8_general_ci”下字符“a”和“A”是等价的。

4.MySQL的字符集支持

     通过命令:show character set和show collation可以分别查看MySQL支持的字符集和排序方式。

5.关于MySQL字符集变量

     使用命令show variables like ‘character%’;可看到当前连接的所有字符集设置。

character_set_client:客户端来源数据使用的字符集

character_set_connection:连接层字符集

character_set_database:当前选中数据库的默认字符集

character_set_results:查询结果字符集

character_set_server:默认的内部操作字符集

character_set_system:系统元数据(字段名等)字符集

 

众所周知,MySQL对于字符集的指定可以细化到一个数据库,一张表,一列,应该使用什么字符集。但是传统的程序在创建数据库和表时并没有使用十分负责的配置,它们用的是默认的配置,那么,默认的配置从何而来呢?

(1)编译MySQL 时,指定了一个默认的字符集,这个字符集是 latin1; (2)安装MySQL 时,可以在配置文件 (my.ini) 中指定一个默认的的字符集,如果没指定,这个值继承自编译时指定的; (3)启动mysqld 时,可以在命令行参数中指定一个默认的的字符集,如果没指定,这个值继承自配置文件中的配置,此时 character_set_server 被设定为这个默认的字符集; (4)当创建一个新的数据库时,除非明确指定,这个数据库的字符集被缺省设定为character_set_server; (5)当选定了一个数据库时,character_set_database 被设定为这个数据库默认的字符集; (6)在这个数据库里创建一张表时,表默认的字符集被设定为 character_set_database,也就是这个数据库默认的字符集; (7)当在表内设置一栏时,除非明确指定,否则此栏缺省的字符集就是表默认的字符集;

简单的总结一下,如果什么地方都不修改,那么所有的数据库的所有表的所有栏位的都用 latin1 存储,不过我们如果安装 MySQL,一般都会选择多语言支持,也就是说,安装程序会自动在配置文件中把default_character_set设置为 UTF-8,这保证了缺省情况下,所有的数据库的所有表的所有栏位的都用 UTF-8 存储。

 

上述6个变量中,除了character_set_client,character_set_connection,character_set_results三个变量之外,其余的变量都是在安装MySQL选择语言时,自动设置的,一般不用特意改变。所以大部分的问题都是出在character_set_client,character_set_connection,character_set_results的不匹配上。

这三个参数的作用如下:

系统变量character_set_client:用来指定解析客户端传递数据的编码

系统变量character_set_connection:用来指定数据库内部处理时使用的编码

系统变量character_set_results:用来指定数据返回给客户端的编码方式

因此我们只要保证上述三个变量的编码方式是一样的,那么编码问题就不会存在。

二. 如何修改默认字符集

1.最简单的修改方法,就是修改/etc/my.ini文件中的字符集默认配置。在[client]下添加上

default-character-set=utf8(这里用utf8举例说明,如果想改成gbk,则该位置设置为gbk即可)

上述方法等同于执行以下3个命令

SET character_set_client =utf8

SET character_set_results =utf8

SET character_set_connection= utf8

2.在创建jdbc连接的时候使用jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&characterSetResults=UTF-8

 

characterEncoding=UTF-8指定了character_set_client、character_set_connection的值。

而characterSetResults=UTF-8则指定了character_set_results的值。与方法一的思路是一样的。

 

3.直接使用sql命令进行修改,在命令行中输入

SET character_set_client = utf8

SET character_set_results = utf8;

SET character_set_connection = utf8;

或者直接输入 set Names utf8 就可以同时修改三个。

4.若使用MySQL客户端 如Navicat之类的,则直接在new connection的时候在Encoding选项中选择utf8 即可

 

还是推荐第一种方法,简单方便,所有的后续操作都不会编码问题。

三. 乱码问题分析

编码问题比较容易出现在共同开发的项目中,一般是由于小组中人员在在通过各种方式连接数据库时,所选择的编码

类型不同。

Ques:数据从web端(web端使用utf8)写入,并在web页面中显示正常,但在数据库中查看却是乱码?

Ans:这里总共有两个连接。 一个是通过jdbc连接的,另一个是自己从mysql客户端建的连接用于直接查看数据库中的

数据。乱码的原因在于建立这两个连接时,设置的编码方式不同。假设,jdbc的连接是jdbc:mysql://localhost:3306/test

?characterEncoding=UTF-8&characterSetResults=UTF-8, 则意味着character_set_client,character_set_connection,

character_set_results 这三个参数都是utf8的。 即数据按照前两个参数的编码类型写入数据库,并且由于

character_set_results 也是utf8的,所以读取时返回的字符集也是utf8的则不会出现乱码。

此时如果自己mysql客户端建立的连接是gbk的, 即该连接的character_set_results是gbk的, 那么通过web端utf8格式

写入的中文字符在读取出来时需要转换为gbk的,那么就会出现乱码。由于utf8的码位远远超过gbk的,所以在gbk

的results看来该码位是不能显示的所以会显示???。 而此时如果你通过gbk的连接输入中文字符,则在web端页面

会显示Ñ¡Ôñ等外文字符,这是由于gbk的码位比utf8少, 对应的gbk的码位是可以在utf8中解析的,只是不能显示正确

的中文字符。

四.结论

我们只要保证character_set_client,character_set_connection,character_set_results

是和你使用的客户端编码格式相同,即如果你的web页面是用utf8的,那么上述三个也必

须是utf8的。如果你项目中已经出现乱码了,那么应该在组内统一编码格式,再对数据库

中的数据进行重新插入。