我们自己鼓捣mysql时,总免不了会遇到这个问题:插入中文字符出现乱码,虽然这是运维先给配好的环境,但是在自己机子上玩的时候咧,总得知道个一二吧,不然以后如何优雅的吹牛B。

如果你也遇到了这个问题,咱先不谈原因,在PC自带的cmd中(或者是mysql安装版安装后的Command Line客户端,又或者是工作用的SecureCRT)试试效果。进入mysql环境,从头开始操作。假设你的客户端编码是gbk或者utf8(这么说太不严谨了,怎么能假设呢,但是一般来说假如安装后没动过,cmd是gbk编码,mysql安装后的Command Line客户端没装不记得,CRT看看Session Options里面的编码设置,一般也会设置成utf8),执行一些语句:

1. 设置编码客户端、连接、返回结果的字符集,先设置成latin1,

2. 然后执行下面的看下各个字符是不是这样的,

如果你的character_set_client、character_set_connection、character_set_results不是latin1,可以这样执行,把他们单个分别设置成latin1,比如设character_set_client,其他两个一样,确保这三个均是latin1(第一步的sql语句实际做的就是这件事),

3. 单独创建一个数据库db_latin1,当然是很简单的了,测试嘛,创建时就设置数据库的编码的为latin1,

4. 在它下面创建一张表tab_latin1,字符集也设置成latin1,这里不设置字符也行,数据库级已经设置了,这里只创建一个name字段,

5. 插入一些中文字符到表中,先说明,本机的cmd编码是gbk,查看方法是右键属性->选项,看下当前代码页即可知道,

6. 查看下结果

看吧,正常显示中文了~~~

OK,都到这儿了你就不想知道“为什么我那样设置就是不行”么,当然得往下看看是不。上图:

我们知道mysql是客户端-服务器软件,每次操作都是客户端向服务端发送请求,然后可能会返回一些结果,这之间插入的字符经过了一系列转换。首先供我们编辑的客户端本身就有一种编码,比如PC端的命令行默认是gbk,PC自带notepad新建文本文件默认是ANSI,常用的文本编辑器如notepad++,我们可能会设置默认编码为utf8,就是说在编辑器上编辑,你所看到的本身就是一种编码了。

1. 在客户端编辑后,首先转化为client对应的字符集,即上面打印出的character_set_client变量指示的字符集;

2. 向数据库服务发送请求,发送过程中,转化为connection对应连接字符集,即character_set_connection变量对应字符集;

3. 存储到数据库中,转化为数据库存储的字符集,可能是server级别(character_set_server)、database级别(character_set_database)或者表级别和列级别(这里还要细说下);

4. 数据库收到请求,执行查询得到结果,再次转化为results对应字符集,即character_set_results变量所指,该结果返回到客户端上;

5. 结果来了,是按照results字符集编码的,那我们让这个结果显示的客户端工具它支持什么样的编码也很重要,这决定了它如何去解码结果。假如这个结果是utf8编码,返回给某客户端了,但这个客户端只有ANSI编码,那当然不能显示正常,比如它返回到SecureCRT,结果显示不正常,但是CRT支持多种编码,我们手动将它调成utf8编码,那它就又显示正常了,所以严格来说这一步算不上,只是跟客户端条件有关,毕竟当我们知道后将客户端调整成正常的编码或者本来就支持转换results的编码后,这一步就不存在了。

在上面的第3步中,从连接字符集编码转化为数据库存储使用的编码时,要分几种情况,一般我们在装mysql时,特别是32位安装版本时,中间有一个选择编码的步骤,大多会选择utf8编码,这时系统就可能会把一系列的字符集变量均设置成了utf8,比如character_set_server、character_set_connection、character_set_database等等。也就是说这个character_set_server变量在你启动mysql服务的事先就被设置好了,我们可以称它为服务器级编码,那我们在建表前,先得创建数据库,在创建数据库时,我们知道可以显式指定编码的,比如最开头时我创建时显式指定采用latin1字符集,也可以不指定,如果不指定的话,它将采用服务器级的字符集,即character_set_server,同理在创建表时,也可不指定编码,不指定的话,采用数据库级编码,级character_set_database,更加同理在创建表中列字段时也可指定编码,不指定编码的话将采用表级别字符集,因此有这么一个继承关系在这:

character_set_server => character_set_database => character set in table(无此变量) => character set column(无此变量)

mysql创建表可以细化到这四个层次,不是每一层都必须指定,默认使用上一级的字符集(字符校对规则也是这样的,collation,稍后说明)。

那么有没有可能character_set_server没有指定呢,如果任何地方都没指定,特别是非安装版中,如果忘了,mysql在编译时默认采用latin1,为了应对这种情况,特别是非安装版本中在配置mysql时,经常需要手动配置mysql配置文件mysql.ini,其中就有大概这么一项:

在配置文件中默认采用的字符集,因此如果指定了character_set_server默认就会采用它,这样其他层次都不指定的话依次继承。

其他的,character_set_filesystem:把操作系统上的字符转换成此字符集,即把character_set_client转换成character_set_filesystem,默认为binary则不转换,character_set_system:此变量总是utf8,为存储系统元字符的字符集,如表名、列名、用户名等,character_set_dir:很明显是指示一个目录的变量,打开这个目录,里边存放的是mysql的各种用于编码字符集的xml格式文件。以上三个值在解决乱码问题时基本可忽视。

好,转换流程和各变量的含义清楚了,就要搞清楚哪些字符集编码之间可以转换,能转换可能也是在一定编码范围内的字符能转换,不至于出现乱码甚至损坏。损坏了就再也无法正确显示了,哪怕设置是正确的,还原是还原不回来的。当然关于字符之间的转化情况很多,字符集有那么多种,随便两个之间都可以转换一下试试,不能一一列举,可以参考这篇文章:http://www.imcjd.com/?p=1324,它针对经常用到的字符转换作了一些转换比较和测试。

其中,可以了解到,完全匹配的转换是肯定没有问题的,比如,gbk->gbk,utf8->utf8,latin1->latin1;转换为单字节编码的latin1也没问题,比如gbk->latin1、utf8->latin1;单字节编码(latin1)转为其他在某些编码某些范围内可能会出现转换不全,比如latin1->gbk(很特殊的中文),或者编码长度改变,比如latin1->utf8,变为2、3等字节数。

下面引用另一篇文章(http://hi.baidu.com/cuttinger/item/f4e79726a60ab450c28d59da)中的一段。

【Latin1是一种很常见的字符集,这种字符集是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。很明显,Latin1覆盖了所有的单字节,因此,可以将任意字符串保存在latin1字符集中,而不用担心有内容不符合latin1的编码规范而被抛弃。——gbk和utf8是多字节编码,没有这种特性。

mysql使用者经常利用Latin1的这种全覆盖特性,将其它类型的字符串,gbk,utf8,big5等,保存在latin1列中。保存的过程中没有数据丢失,只要原样取出来,便又是合法的gbk/utf8/big字符串。如果将gbk字符串保存在utf8列中,则gbk字符串中那些不符合utf8编码格式的内容,会被抛弃,保存的内容无法原样取出,数据实际上遭到了破坏。

综上,如果我们看到一个字段的字符集是latin1的,那么,他保存的可能是任何编码的字符串;而一个字段的字符集是utf8或者gbk的,那么他保存的就应该是utf8或gbk的——除非数据库的使用者用错了。】

我没有深入学习过utf8、gbk编码的细节,极可能说的不准确,只知道简单的ASCII编码(-_-),但是可以了解个全局情况。从上面来看,latin1的单字节编码方式很有用,其他的编码可以转换为它再转回去而不至于丢失内容。所谓单字节编码就是挨着一个个来,我理解是,比如圣诞节到了,你要送妹子一箱苹果,为制造浪漫,商铺提供两种包装方式,一是按个数来,即单个苹果包装进一个盒子,来一个包装一个,这样,妹子在拆完所有的盒子后完完整整的可以还原为一个个完整的和一箱完好无损的苹果,二是按重量来,每个盒子限重2两、3两、6两,这样在包装时,若刚好重3两的当然可以完整的放进一个盒子,但是若不够或者多了,勉不了要切开苹果,或者再往盒子中添加其他的部分苹果,这样的话,妹子再无论怎样拆开盒子,都会得到一箱残缺不堪的苹果了,因为你在按照这种包装方式进行时,已经破坏了单个苹果的完整性,现在还原不回来了~我们的字符集编码转换就是在做这种重新包装的工作,latin1恰好就像单个苹果包装,而utf8就像第二种方式。

而刚才说的完全匹配的情况是,你去买一箱苹果,箱子里边的所有苹果重量已经恰好要么是2两,要么是3两或6两的,这样再按重量包装时当然就恰好分配了,得到的仍然是完整的苹果。

所以说白了,几种可行的方式是:

1. 所有变量均设置成latin1(set names latin1;),这样,即便我们所使用的编辑客户端编码多样(gbk或utf8),最终可以得到正确结果;

2. 所有的设置成gbk或者gb2312(国标编码,只用于简体中文),采用完全匹配;

最后,关于字符集校对规则,只了解一点。在我们设置mysql字符集时,mysql会自动给一个对应的校对规则,比如设置charset为utf8,默认的collation就是utf8_general_ci,gb2312字符集对应gb2312_chinese_ci,mysql命令查看所有校对规则是show collation,查看某一对应字符集的校对规就是show collation like 'utf8%'了。

字符集校对是一种对使用当前字符集时采用的排序、对比方式,即便同一种字符集,在不同的地区也是不同的对比方式,所以才有校对这么一说,比如utf8_general_ci,这个ci就是case insensitive,即大小写不敏感,采用它校对时,查询某字段值匹配时,大小写的记录都会出现,当然还有其他的规则,utf8打印出来一大坨,不细研究了~

参考文章:

http://www.blogjava.net/wldandan/archive/2007/09/04/142669.html

http://hi.baidu.com/cuttinger/item/f4e79726a60ab450c28d59da

http://www.imcjd.com/?p=1324

http://www.360doc.com/content/11/0303/01/2588264_97631236.shtml

http://blog.csdn.net/my_mao/article/details/30498313

----------------------------------------------------------------------------------------------------

  偶然看到鸟哥整理的一篇http://www.laruence.com/2008/01/05/12.html,基本概念解释得言简意赅,毕竟大神,参考性强,能验证的部分还是手动验证为好。

转载于:https://www.cnblogs.com/lazycat-cz/p/4213570.html

mysql中文乱码的一点理解相关推荐

  1. mysql java 中文_mysql +java 中文乱码问题彻底理解和解决

    | 1 | ????MySQL???????? | | 2 | ??MySQL?? | | 3 | 测试MySQL编码 | +----+-------------------+ 现在可以看到中文正常显 ...

  2. 图形化mysql出现乱码_关于Mysql中文乱码问题该如何解决(乱码问题完美解决方案)...

    最近两天做项目总是被乱码问题困扰着,这不刚把mysql中文乱码问题解决了,下面小编把我的解决方案分享给大家,供大家参考,也方便以后自己查阅. 首先: 用show variables like &quo ...

  3. 【转】QT中使用MYSQL中文乱码解决方法

    [转]QT中使用MYSQL中文乱码解决方法 Linux下乱码解决办法: 1.在QT程序的main.cpp的main函数中添加红色字那三句: int main(int argc, char *argv[ ...

  4. sqoop导出到mysql中文乱码问题总结、utf8、gbk

    sqoop导出到mysql中文乱码问题总结.utf8.gbk 今天使用sqoop1.4.5版本的(hadoop使用cdh5.4)因为乱码问题很是头痛半天.下面进行一一总结 命令: [root@sdzn ...

  5. c# mysql 编码_c# 连接MySQL中文乱码问题的正确方案

    以下的文章主要向大家介绍的是c# 连接MySQL中文乱码问题的正确解决方法,一开始不太清楚为什么整个数据库的默认配置都为utf-8,而且有些人在使用http协议传送utf-8的汉字时,是正确的执行了的 ...

  6. c 访问mysql 乱码_c语言连接mysql中文乱码怎么办

    c语言连接mysql中文乱码怎么办 发布时间:2020-06-30 13:42:44 来源:亿速云 阅读:96 作者:清晨 这篇文章主要介绍c语言连接mysql中文乱码怎么办,文中示例介绍的非常详细, ...

  7. C# 连接 Mysql 中文乱码问题

    如题这个问题还是让人比较揪心的.网上也有不少答案,五花八门,不知道谁对谁错.个人认为有几篇文章处理的这个问题还不错,现总结如下: 第一篇: c#连接MySQL解决汉字乱码 突然发现我的数据表中,有汉字 ...

  8. Servlet、MySQL中文乱码

    1.Servlet中文乱码: 在doPost或doGet方法里,加上以下两行即可: response.setContentType("text/html;charset=UTF-8" ...

  9. tomcat mysql 中文乱码_tomcat 中文乱码, mysql 中文乱码_MySQL

    Tomcat tomcat中文乱码 get 请求. 修改server.xml中的添加URIEncoding='UTF-8' tomcat中文乱码 post 版 另外HttpURLConnection上 ...

最新文章

  1. setup vaio winxp
  2. Android 5.1上MultiDex异常: DexPathList NoSuchMethodException makeDexElements
  3. 菜鸟学习Javascript20170116
  4. 安装DirectX SDK时出现Error Code:s1023 的解决方案
  5. SystemC 代码添加和测试方法
  6. 介绍一种新的激活函数族ACON
  7. python装饰器property_python装饰器: @property
  8. python关于组合数据类型_python组合数据类型
  9. 时间序列预测入门必读的4篇论文
  10. 自学数据科学机器学习,19个数学和统计学公开课推荐
  11. 计算机专业基础 -- 数据库系统相关基础知识
  12. 嵌入式软件工程师就只需会写C代码吗
  13. 系统中 用户操作日志管理
  14. 笔记本电脑插入耳机只能外放,耳机没声音
  15. Andriod+SpringBoot 图书馆管理系统
  16. 电脑怎么提取图片中的文字?
  17. 一份价值上万的年终总结 —— 自我重构
  18. IE6兼容PNG_se7en3_新浪博客
  19. 《利用Python进行数据分析》笔记记录第六章——数据载入、存储及文件格式
  20. 安卓P 刘海屏的适配

热门文章

  1. 《软件工程》总结——第十一章
  2. mmz-asio4delphi死链接的解决办法
  3. [转载]Guice 1.0 用户指南
  4. mysqldatareader什么意思_MySqlDataReader在Using中使用
  5. div css导航栏设计,CSS+DIV设计实例:超酷的竖排导航栏
  6. android动态加载宽高,动态添加LinearLayout的高度实例
  7. java stringbuilder appendline_StringBuilder
  8. Python自动化开发学习15-css补充内容
  9. git 常用命令整理
  10. SSE图像算法优化系列一:一段BGR2Y的SIMD代码解析。