Mysql中文乱码解决思路和过程

Mysql 中文乱码问题是常见的问题,解决也是不难的,本文将通过我在遇到问题时候,如何的查找和解决为导向,来呈现分析解决问题的思路和过程。

    在JavaEE项目开发中,通常的中文乱码问题分为web前端,web后端,数据库乱码,如果想查看web端的中文乱码问题,请参照博文http://blog.csdn.net/songdeitao/article/details/17577823,一但排除了web端的中文乱码,也就说乱码问题是在数据库端发生的了。

问题产生:

    首先在创建用户,如图1所示:

Mysql中文乱码解决思路和过程_第1张图片

              图1

    在点击增加用户的时候,数据库中userName字段显示为乱码:

[sql]  view plain copy
  1. mysql> select * from t_user;  
  2. +--------+----------+------+---------------------+-------+  
  3. | userId | userName | age  | birthday            | isVip |  
  4. +--------+----------+------+---------------------+-------+  
  5. |      1 | ????     |    0 | 2014-01-01 00:00:00 |     1 |  
  6. +--------+----------+------+---------------------+-------+  
  7. 1 row in set (0.00 sec)  

解决思路

    在javaweb项目中,在解决乱码问题之前,首先要确保是在数据库这里发生乱码,如果确实在数据库这端发生乱码,请试着通过以下步骤查找原因:

步骤一:查看数据库编码状态,如下所示:
[sql]  view plain copy
  1. mysql> status;  
  2. --------------  
  3. mysql  Ver 14.12 Distrib 5.0.22, for Win32 (ia32)  
  4.   
  5. Connection id:          3  
  6. Current database:       steven  
  7. Current user:           root@localhost  
  8. SSL:                    Not in use  
  9. Using delimiter:        ;  
  10. Server version:         5.0.22-community-nt  
  11. Protocol version:       10  
  12. Connection:             localhost via TCP/IP  
  13. Server characterset:    latin1  
  14. Db     characterset:    latin1  
  15. Client characterset:    latin1  
  16. Conn.  characterset:    latin1  
  17. TCP port:               3306  
  18. Uptime:                 2 hours 10 min 15 sec  
  19.   
  20. Threads: 1  Questions: 121  Slow queries: 0  Opens: 2  Flush tables: 1  Open tab  
  21. les: 0  Queries per second avg: 0.015  
  22. --------------  

       发现Server,Db,Client,Conn.的字符编码均为latin1,所以一定会出现中文乱码的情况。
解决方案一:(window下)
通过MySQL Server Instance Configuration Wizard重新设置编码方案,如图2所示:
Mysql中文乱码解决思路和过程_第2张图片
                      图2
然后一直Next,然后到Please select the database usage 的时候选择第三项,如图3所示:
Mysql中文乱码解决思路和过程_第3张图片
                      图3
接着一直Next,到Please select the default character set.的时候选择gbk,字符编码,如图4所示:

                  图4
这个时候一直Next,确认密码后,Next,然后就Execute执行,如图5所示:
Mysql中文乱码解决思路和过程_第4张图片
                    图5
Finish后,退出数据库命令控制台然后再进去,查看数据库编码状态,如下所示:
[sql]  view plain copy
  1. mysql> use steven;  
  2. Database changed  
  3. mysql> status;  
  4. --------------  
  5. mysql  Ver 14.12 Distrib 5.0.22, for Win32 (ia32)  
  6.   
  7. Connection id:          2  
  8. Current database:       steven  
  9. Current user:           root@localhost  
  10. SSL:                    Not in use  
  11. Using delimiter:        ;  
  12. Server version:         5.0.22-community-nt  
  13. Protocol version:       10  
  14. Connection:             localhost via TCP/IP  
  15. Server characterset:    gbk  
  16. Db     characterset:    latin1  
  17. Client characterset:    gbk  
  18. Conn.  characterset:    gbk  
  19. TCP port:               3306  
  20. Uptime:                 1 min 20 sec  
  21.   
  22. Threads: 1  Questions: 12  Slow queries: 0  Opens: 0  Flush tables: 1  Open tabl  
  23. es: 6  Queries per second avg: 0.150  
  24. --------------  
发现编码除了Db characterset外其他的都改为gbk了,这是方案一,依然可以实现这样的更改。

解决方案二:通过配置文件,找到Mysql安装的目录,找到根目录下my.ini文件,如图6所示:

     图6
然后打开后,进行如下更改,如图7所示:
Mysql中文乱码解决思路和过程_第5张图片
                       图7
将latin1更改gbk编码方式,
然后将数据库服务重新启动,如下所示:
[sql]  view plain copy
  1. C:\Users\Administrator>net stop mysql  
  2. The MySQL service is stopping.  
  3. The MySQL service was stopped successfully.  
  4.   
  5.   
  6. C:\Users\Administrator>net start mysql  
  7. The MySQL service is starting.  
  8. The MySQL service was started successfully.  
这个时候和方案一一样的效果,然而此时并没有解决问题。
[sql]  view plain copy
  1. mysql> use steven;  
  2. Database changed  
  3. mysql> status;  
  4. --------------  
  5. mysql  Ver 14.12 Distrib 5.0.22, for Win32 (ia32)  
  6.   
  7. Connection id:          2  
  8. Current database:       steven  
  9. Current user:           root@localhost  
  10. SSL:                    Not in use  
  11. Using delimiter:        ;  
  12. Server version:         5.0.22-community-nt  
  13. Protocol version:       10  
  14. Connection:             localhost via TCP/IP  
  15. Server characterset:    gbk  
  16. Db     characterset:    latin1  
  17. Client characterset:    gbk  
  18. Conn.  characterset:    gbk  
  19. TCP port:               3306  
  20. Uptime:                 1 min 20 sec  
  21.   
  22. Threads: 1  Questions: 12  Slow queries: 0  Opens: 0  Flush tables: 1  Open tabl  
  23. es: 6  Queries per second avg: 0.150  
  24. --------------  

步骤二:改变Db characterset的编码方式,执行以下sql语句:
[sql]  view plain copy
  1. --修改数据库编码为gbk  
  2. alter database steven character set gbk;   
其中steven是数据表乱码所在的数据库,这个时候执行status查看
[sql]  view plain copy
  1. mysql> status;  
  2. --------------  
  3. mysql  Ver 14.12 Distrib 5.0.22, for Win32 (ia32)  
  4.   
  5. Connection id:          2  
  6. Current database:       steven  
  7. Current user:           root@localhost  
  8. SSL:                    Not in use  
  9. Using delimiter:        ;  
  10. Server version:         5.0.22-community-nt  
  11. Protocol version:       10  
  12. Connection:             localhost via TCP/IP  
  13. Server characterset:    gbk  
  14. Db     characterset:    gbk  
  15. Client characterset:    gbk  
  16. Conn.  characterset:    gbk  
  17. TCP port:               3306  
  18. Uptime:                 8 min 30 sec  
  19.   
  20. Threads: 1  Questions: 32  Slow queries: 0  Opens: 1  Flush tables: 1  Open tabl  
  21. es: 7  Queries per second avg: 0.063  
  22. --------------  
此时都成为gbk的编码格式了。
    注:如果此时数据库编码默认就为gbk的编码方式的,此时问题一般都已经解决了,如果还没有解决,在插入含有中文数据的时候会有以下异常:
[java]  view plain copy
  1. com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'userName' at row 1  
  2.     at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3489)  
  3.     at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3423)  
  4.     at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1936)  
  5.     at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2060)  
  6.     at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2542)  
  7.     at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1734)  
  8.     at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2019)  
  9.     at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1937)  
  10.     at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1922)  
  11.     at com.steven.util.DaoHandle.executeDML(DaoHandle.java:49)  
  12.     at com.steven.dao.impl.UserDao.doCreate(UserDao.java:33)  
  13.     at com.steven.model.UserAddAction.execute(UserAddAction.java:80)  
  14.     at com.steven.controller.ActionServlet.doPost(ActionServlet.java:40)  
  15.     at javax.servlet.http.HttpServlet.service(HttpServlet.java:643)  
  16.     at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)  
  17.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)  
  18.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)  
  19.     at com.steven.util.EncodeFilter.doFilter(EncodeFilter.java:35)  
  20.     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)  
  21.     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)  
  22.     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)  
  23.     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)  
  24.     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)  
  25.     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)  
  26.     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)  
  27.     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)  
  28.     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)  
  29.     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)  
  30.     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)  
  31.     at java.lang.Thread.run(Thread.java:722)  

说数据过长,此时查看数据表默认编码方式如下所示:
[sql]  view plain copy
  1. mysql> show create table t_user;  
  2. +--------+----------------------------------------------------------------------  
  3. --------------------------------------------------------------------------------  
  4. --------------------------------------------------------------------------------  
  5. ----------------------------------------+  
  6. Table  | Create Table  
  7.   
  8.   
  9.                                         |  
  10. +--------+----------------------------------------------------------------------  
  11. --------------------------------------------------------------------------------  
  12. --------------------------------------------------------------------------------  
  13. ----------------------------------------+  
  14. | t_user | CREATE TABLE `t_user` (  
  15.   `userId` int(10) NOT NULL auto_increment,  
  16.   `userName` varchar(100) NOT NULL,  
  17.   `age` int(2) default NULL,  
  18.   `birthday` datetime default NULL,  
  19.   `isVip` tinyint(1) default NULL,  
  20.   PRIMARY KEY  (`userId`)  
  21. ) ENGINE=MyISAM DEFAULT CHARSET=latin1 |  
  22. +--------+----------------------------------------------------------------------  
  23. --------------------------------------------------------------------------------  
  24. --------------------------------------------------------------------------------  
  25. ----------------------------------------+  
  26. 1 row in set (0.00 sec)  
会发现数据表默认编码是latin1,所以异常的原因就是中文的编码和表的默认编码不匹配,造成数据冲突引起的。

步骤三:解决异常
执行以下两句进行更改数据库的默认编码方式;
方案一:drop表,然后重新建表,建表语句如下所示;
[sql]  view plain copy
  1. create table t_user(  
  2.     userId      int(10)  not null primary key auto_increment,  
  3.     userName    varchar(100) not null,  
  4.     age         int(2),  
  5.     birthday    datetime,  
  6.     isVip       boolean  
  7. DEFAULT CHARSET=gbk;  
方案二:mysql自带的命令
执行以下两句命令:
[sql]  view plain copy
  1. --修改表默认用gbk  
  2. alter table t_user character set gbk;  
  3. --修改userName字段编码为gbk  
  4. alter table t_user modify userName varchar(100) CHARACTER SET gbk;   
执行完之后,数据库字段和表的编码方式都更改为了gbk,此时在进行插入数据时候,数据表中的数据为:
[sql]  view plain copy
  1. mysql> select * from t_user;  
  2. +--------+----------+------+---------------------+-------+  
  3. | userId | userName | age  | birthday            | isVip |  
  4. +--------+----------+------+---------------------+-------+  
  5. |      1 | ????     |    0 | 2014-01-01 00:00:00 |     1 |  
  6. |      2 | 元旦快乐 |    0 | 2014-01-01 00:00:00 |     1 |  
  7. +--------+----------+------+---------------------+-------+  
  8. rows in set (0.00 sec)  
第一条为乱码时候插入的数据,第二条为解决后插入的数据,此时Mysql数据库编码已经解决了。

总结:
对于数据库乱码解决方案,可以归纳如下:
  1. 通过软件或者配置文件进行第一步修改编码
  2. 通过mysql命令更改数据库编码(如果默认编码支持中文,此步骤就可以省略了)
  3. 发生Data too long for column……异常,进行数据表字符编码更改
    一般情况的mysql数据库中文编码问题即可得到解决,编码同样可以设置成utf8编码方式,但有时会出现数据库中编码是繁体字的现象,然后执行set names "gbk"命令,即可成功显示简体中文。
    下面提供常用的修改中文字符乱码的mysql命令:
[sql]  view plain copy
  1. set names 'gbk';   
  2. --它相当于下面的三句指令:   
  3. set character_set_client = gbk;   
  4. set character_set_results = gbk;   
  5. set character_set_connection = gbk;   
  6.   
  7. --显示数据表表的编码  
  8.  show create table t_user(表的名称);  
  9.    
  10.  --修改数据库编码为gbk  
  11.  alter database steven(数据库的名称) character set gbk;   
  12.    
  13. --修改表默认用gbk  
  14. alter table t_user(表的名称) character set gbk;  
  15.   
  16. --修改userName字段编码为utf8  
  17. alter table t_user(表的名称) modify userName(表中字段的名称) varchar(100) CHARACTER SET gbk;   
  18.   
  19. --创建表  
  20. create table t_user(  
  21.     userId      int(10)  not null primary key auto_increment,  
  22.     userName    varchar(100) not null,  
  23.     age         int(2),  
  24.     birthday    datetime,  
  25.     isVip       boolean  
  26. DEFAULT CHARSET=gbk;  
原文:http://blog.csdn.net/songdeitao/article/details/17711015

你可能感兴趣的:(java,数据库,mysql,javaee,乱码)