MySQL入门集锦(四)

go on go on~~~
今天的主要是编码问题,在学习一门语言的过程中,编码是不可避避免遇到的问题,而且有时候一困扰就会让人挠破脑袋,所以接下来我们一起了解一下每一种编码吧~
编码的产生:
由于计算机只有0和1两种符号,但人的世界里有更为复杂的东西,所以就出现了人为规定。
例如,0100 0001 是表示A,还是65?这就要看上下文环境来决定。
首先,我们先来了解一些编码的发展历史。
一、编码发展
1、ASCII码( American Standard Code for Information Interchange )
这是最早使用的编码方式,这是美国发明的一种方式,它们认为英文字符总数少于127,所以它们用一个字节的位置来代表不同的字符。一个字节有八个比特,一个有256个不同的结果,所以ASCII的最高为长为0来表示不同的字符。
MySQL入门集锦(四)
ASCII码对照表
2、GB2312
但是ASCII码引用到中文汉字中,发现ASCII码不够用,因为中国汉字大概有四五千字,而ASCII码最多也就是256种,所以就出现了用两个字节来表示,两个字节一共能表示65535种,对于中国汉字是足够了。由于所有的编码方式都是兼容ASCII码的,而前面的[0-127]已经被ASCII占用了,为了能够分辨出中英文,所以同意规定中文使用[129-255]这个范围,此时编码能够识别中英文,但是识别中文的个数变少了,实际上GB2312一共收录了6千多个字。对于我们常用的汉字是够用的,但是一些生僻字就不能识别了,例如:“*”的“镕”就没有录入其中,所以就又产生了新的编码集,GBK。
3、GBK
为了解决gb2312的问题,产生GBK编码集。gbk同样占用了两个字节,我们规定gbk的第二位是可以使用ASCII中的范围。此时,我们从左往右识别时,当第一个字节大于127,则向后绑定一位识别中文,当第一个字节小于127,则直接识别为英文,据统计GBK总共收录了21003个汉字,883个符号,并提供了1897个造字码位。
4、ANSI 本地字符集
在中国代表GBK,但是不同国家的规则不同,会出现乱码问题,所以,就需要产生一种国际化的编码,Unicode。
5、Unicode
一个世界通用的码表,将各个国家的所有字符都给定一个确定的表示,同一分配编号。占用了4个字节,大小约为42亿,足够囊括所有字符,但是我们常用的集中在前2个字节里。但是unicode只负责用4个字节来分配编号,但是却造成了一定的浪费 ,同时要在网络上传输就需要简化,所以就产生了一系列简化集。
6、UTF-8
Unicode只是负责编号,要在网络上进行传输就需要简化,而unicode的实现方式称为Unicode转换格式,简称UTF(可以理解为一种无所压缩)。Unicode与UTF-8的关系就像是原文件与压缩文件的关系。UTF-8是一种变长编码,占用1-6个字节。由于这种不定长的存储,我们要怎么确定字符边界呢?
MySQL入门集锦(四)
Unicode与UTF-8转换对照表
我们是这样确定的,从第一个字节读起,若第一个字节为0....则占用一个子节,若110....则是两个字节,以此类推。
从容量上看,GB2312 < GBK < UTF-8。
当GBK转成UTF-8格式时,需要借助Unicode作为中介。
二、乱码的形成
1、解码是与实际编码不一致。比如,写入文本是utf8,但是识别时你指定了gbk格式,那么就会造成乱码,这种乱码是能够修复,只需要指定正确的解码格式就可以了。
2、传输过程中,编码不一致导致字节丢失。比如讲utf8转成gb2312,由于gb2312的容量较小,utf-8中的一些字符无法识别则会被舍弃,造成不可修复的后果。
三、MySQL中的字符集问题
数据库中由于存储数据所用的编码方式时一定是utf-8。  
MySQL入门集锦(四)
数据存储到数据库以及读取数据时的流程
在数据库中通常涉及三种编码参数,客户端编码、连接器编码以及查询结果编码。
  • 当客户端字符集为gbk,连接器字符集为utf8时,整个存储过程的转换为:
gbk --> 转换,转换成utf8 -->不转换, 交给服务器
  • 当客户端字符集为gbk,连接器字符集为gbk时,整个存储过程的转换为:
gbk --> 不转换,交到connection -->转换成utf8,交给服务器
此时关于存储时涉及的编码有客户端编码和连接器编码,在MySQL中可以通过以下语句来指定:
character_set_client=编码方式;(指定客户端的编码方式)
character_set_connection=编码方式;(指定连接器的编码方式)
而对于我们从数据库中查询的结果也可以指定编码方式
character_set_results=编码方式;
通过三层指定,我们就可以避免乱码了。
MySQL入门集锦(四)
直接查找数据发现中文乱码了;
我们指定查询结果的字符集为gbk,因为本人命令行是gbk编码的。
MySQL入门集锦(四)
发现不会乱码了。
思考:gbk的容量比utf-8的小,那么当客户端的编码是utf-8而连接器的编码是gbk时,不会造成字节丢失吗?
答:在中文网站的话我们使用的常用字基本集中在前两个字节,所以问题不大,但是理论上是有可能出现乱码的。
而我们在MySQL中经常看到的set names gbk;这个语句,其实就是同时将上述三种编码方式统一设置为gbk,这就肯定不会出现乱码了。
服务器的编码基本原则:client端 <= 连接器端 <= 服务器
总结:牵涉到数据库,要想不乱码:
1、正确指定客户端的编码;
2、合理选择连接器的编码;
3、正确指定返回内容的编码。
特别解释:utf-8、UTF-8、utf8表示的都是utf-8编码,只是在不同的软件环境下写法不同,比如MySQL中使用的是utf8。