Mysql字符集知识总结

字符集&字符编码方式mysql

     字符集(Character set)是多个字符的集合,字符集种类较多,每一个字符集包含的字符个数不一样,这里的字符能够是英文字符,汉字字符,或者其余国家语言字符。
常见字符集包括:ASCII字符集、LATIN1字符集、GB2312字符集、GBK字符集、GB18030字符集、Unicode字符集等。字符编码方式是用一个或多个字节表示字符集中的一个字符。每种字符集都有本身特有的编码方式,所以同一个字符,在不一样字符集的编码方式下,会产生不一样的二进制。ASCII是基于罗马字母表的一套字符集,它采用1个字节的低7位表示字符,高位始终为0。LATIN1字符集相对于ASCII字符集作了扩展,仍然使用一个字节表示字符,但启用了高位,扩展了字符集的表示范围。GB23十二、GBK、GB18030字符集是支持中文的字符集,字符集范围GB2312<GBK< GB18030。GBK字符集的字符有一字节编码和两字节编码方式。对于00-7F的字符与ASCII保持一致,汉字采用2个字节表示。第一字节范围是81-FE,避免与00-7F冲突。Unicode字符集是计算机科学领域里的一项业界标准,支持了全部国家的文字字符。Unicode字符集有好几种编码方式,好比常见的utf-8,utf-16,utf-32等。Utf8采用1-4个字节表示字符,utf-16采用固定的2个字节,utf-32则采用4个字节存储。算法

mysql与字符集sql

      只要涉及到文字的地方,就会存在字符集和编码方式。对于mysql数据库系统而言,用户从mysql client端敲入一条sql语句,经过TCP/IP传递给mysql server进程,到最终存入server端的文件,每一个环节都涉及到字符存储。涉及到字符存储的地方,就涉及到字符集编码,经过mysql提供的系统变量就可见一斑。mysql字符集设置系统变量以及含义以下表:数据库

变量名编码

含义spa

character_set_server命令行

默认的内部操做字符集code

character_set_clientserver

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

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)  查看字符集编码设置

SHOW VARIABLES LIKE%CHARACTER%

2)  设置字符集编码

SET NAMES xxx;

这个语句至关于设置了client的字符集,主要包含3个系统变量,character_set_client,character_set_connection和character_set_results。

3) 修改数据库字符集

ALTER DATABASE  DATABASENAME  CHARACTER SET XXX;

这个语句只修改库的字符集,影响后续建立的表的默认定义;对于已建立的表的字符集不受影响。

4) 修改表的字符集

ALTER TABLE TABLENAME CHARACTER SET XXX;

这个语句只修改表的字符集,影响后续该表新增列的默认定义,已有列的字符集不受影响。

ALTER TABLE TABLENAME CONVERT TO CHARACTER SET XXX;

 这个语句同时修改表字符集和已有列字符集,并将已有数据进行字符集编码转换。

5) 修改列字符集

ALTER TABLE `TABLE_NAME` MODIFY COLUMN `COLUMN_NAME`  CHARACTER SET 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

     mysql 4.x版本以前默认采用的是latin1字符集(又称ISO-8859-1),latin1字符集编码方式采用单字节编码。抛一个问题,latin1字符集的表,用户写入和读取汉字是否有问题?答案是只要合理设置,没有问题。假设SecureCRT为UTF8,character_set_client和表字符集均设置为latin1,参考第3节的分析,那么用户读取和写入数据的过程当中,并不涉及字符集编码转换的问题,将UTF8的汉字字符转为二进制流写入database,提取出来后,secureCRT再将对应的二进制解码为对应的汉字,因此不影响用户的使用。可是,若character_set_client,character_set_connection,与表字符集设置等不统一,就可能出现乱码的状况。

相关文章
相关标签/搜索