您好,欢迎访问一九零五行业门户网

MySQL字符集知识总结

只要涉及到文字的地方,就会存在字符集和编码方式。对于mysql数据库系统而言,用户从mysql client端敲入一条sql语句,通过tcp/ip
字符集&字符编码方式
字符集(character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,这里的字符可以是英文字符,汉字字符,或者其他国家语言字符。
常见字符集包括:ascii字符集、latin1字符集、gb2312字符集、gbk字符集、gb18030字符集、unicode字符集等。字符编码方式是用一个或多个字节表示字符集中的一个字符。每种字符集都有自己特有的编码方式,因此同一个字符,在不同字符集的编码方式下,会产生不同的二进制。ascii是基于罗马字母表的一套字符集,它采用1个字节的低7位表示字符,高位始终为0。latin1字符集相对于ascii字符集做了扩展,仍然使用一个字节表示字符,但启用了高位,扩展了字符集的表示范围。gb2312、gbk、gb18030字符集是支持中文的字符集,字符集范围gb2312mysql与字符集
只要涉及到文字的地方,就会存在字符集和编码方式。对于mysql数据库系统而言,用户从mysql client端敲入一条sql语句,通过tcp/ip传递给mysql server进程,到最终存入server端的文件,每个环节都涉及到字符存储。涉及到字符存储的地方,就涉及到字符集编码,通过mysql提供的系统变量就可见一斑。mysql字符集设置系统变量以及含义如下表:
变量名
含义
character_set_server
默认的内部操作字符集
character_set_client
客户端来源数据使用的字符集
character_set_connection
连接层字符集
character_set_results
查询结果字符集
character_set_database
当前选中数据库的默认字符集
character_set_system
系统元数据(字段名等)字符集
以上这些参数如何起作用
1.库、表、列字符集的由来
(1).建库时,若未明确指定字符集,则采用character_set_server指定的字符集。
(2).建表时,若未明确指定字符集,则采用当前库所采用的字符集。
(3).新增,修改表字段时,若未明确指定字符集,则采用当前表所采用的字符集。
2.更新、查询涉及到得字符集变量
用户在更新(插入,删除,修改),查询数据库时,最常使用的字符集变量主要包含character_set_client,character_set_connection,character_set_result。
更新流程字符集转换过程:character_set_client-》character_set_connection-》表字符集。
查询流程字符集转换过程:表字符集-》character_set_result
ps:个人认为character_set_connection连接字符集设置有点冗余,因为最终都是要转换到表字符集的。
3.character_set_database
这个参数是当前默认数据库的字符集,比如执行use xxx后,当前数据库变为xxx,若xxx的字符集为utf8,那么这个变量值就变为utf8。因此这个参数是供系统设置,无需人工设置。
mysql字符编码转换流程
      如果以上各个系统变量的设置不一致,比如character_set_client为utf8,而character_set_database为gbk,则会出现需要进行编码转换的情况。那么字符集转换的原理是什么?假设gbk字符集的字符串“小明”,需要转为utf8字符集存储,实际就是对于“小明”字符串中的每个汉字去utf8编码表里面查询对应的二进制,然后存储,仅此而已,编码转换并不涉及到复杂的算法。mysql字符集转换主要涉及到几个步骤:
1) 将数据从character_set_client设置转换为character_set_connection设置;
2) 将character_set_connection设置转为表字段的字符集设置;
3) 将操作结果从表字段字符集转为character_set_results设置。
下面我通过一个常用的场景来描述字符集转换的流程。用户通过mysql命令行(如果是远程连接:securecrt),,敲入命令“insert into t values(1,’小明’)”,字符串’小明’在流转过程中二进制存储内容。
a) 用户采用的客户端为utf8字符集,character_set_client=gbk,character_set_connection=gbk, 表t采用gbk字符集。
由于character_set_client、character_set_connection和表字符集均为gbk,不涉及编码转换。因此,表虽然为字符集虽然为gbk,但“小明”的编码并非为gbk编码的二进制流,而是utf8的二进制流,两个汉字占用了6个字节,而读取则是一个逆向的过程,不涉及到编码转换,查询依然能正确返回“小明”。
b)  在a)的情况下,改变character_set_client的设置为utf8,查询插入的值。
可以看到返回的值是“灏忔槑”, 这是由于表的字符集是gbk,而客户端请求是utf8,那么server将二进制流e5b08fe6988e对应的gbk汉字“灏忔槑”转为utf8汉字对应的二进制流e7818fe5bf94e6a791,因此查询结果在securecrt就显示为“灏忔槑”,即通常我们所谓的乱码。
c) 在b)的情况下,设置securecrt的字符集为gbk,看看securecrt字符集设置对结果影响
可以看到返回的是另外一组字符“鐏忓繑妲”,整个流转过程与b)一样,只是在第一步发生了字节流转换,设置securecrt字符集编码,只是改变了显示方式。
字符集相关的sql语句
1)  查看字符集编码设置

2)  设置字符集编码
set names xxx;
这个语句相当于设置了client的字符集,主要包含3个系统变量,character_set_client,character_set_connection和character_set_results。
3) 修改数据库字符集
xxx;
这个语句只修改库的字符集,影响后续创建的表的默认定义;对于已创建的表的字符集不受影响。
4) 修改表的字符集
xxx;
这个语句只修改表的字符集,影响后续该表新增列的默认定义,已有列的字符集不受影响。
xxx;
 这个语句同时修改表字符集和已有列字符集,并将已有数据进行字符集编码转换。
5) 修改列字符集
xxx
6)  查询字符的二进制编码
select hex(col_name) from table_name;select length(col_name) from table_name;
对于gbk的表,如果查出来一个字符占用了3个字节,比如图1这种情况,则肯定是字符集在某个环节设置统一,图1就是因为客户端是utf8,而mysqlclient和database都是gbk造成的。
mysql默认的字符集latin1
其它类似信息

推荐信息