字符集
将一个字符映射成一个二进制数据的过程也叫做编码
将一个二进制数据映射到一个字符的过程叫做解码
表示一个字符需要的字节数可能不同的编码方式称为变长编码方式
比较规则
二进制比较规则: 直接比较这两个字符对应的二进制编码的大小
同一种字符集可以有多种比较规则,如不区分大小写时,先将字符都转为大写或小写,再比较对应映射二进制的大小
重要的字符集
ASCII
字符集收录128个字符,包括空格、标点符号、数字、大小写字母和一些不可见字符,使用1个字节进行编码
ISO 8859-1
字符集收录256个字符,在
ASCII
字符集的基础上又扩充了128个西欧常用字符(包括德法两国的字母),使用1个字节进行编码,别名latin1GB2312
字符集收录了汉字以及拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母。其中收录汉字6763个,其他文字符号682个。兼容
ASCII
字符集,如果字符在ASCII
字符集中,则采用1字节编码,否则采用2字节编码
GBK
字符集在收录字符范围上对
GB2312
字符集作了扩充,编码方式兼容GB2312utf8
字符集收录地球上能想到的所有字符,而且还在不断扩充。兼容
ASCII
字符集,采用变长编码方式,编码一个字符需要使用1~4个字节准确的说,utf8只是Unicode字符集的一种编码方案,Unicode字符集可以采用utf8、utf16、utf32这几种编码方案,utf8使用1~4个字节编码一个字符,utf16使用2个或4个字节编码一个字符,utf32使用4个字节编码一个字符
MySQL中支持的字符集和排序规则
MySQL中的utf8和utf8mb4
在MySQL
中字符集表示一个字符所用最大字节长度在某些方面会影响系统的存储和性能,所以MySQL
定义了两个概念:
utf8mb3
:阉割过的utf8
字符集,使用1~3个字节表示字符,别名utf8utf8mb4
:正宗的utf8
字符集,使用1~4个字节表示字符,适用需要使用4字节编码一个字符的情况,如存储emoji表情
查看MySQL
中支持的字符集:
SHOW (CHARACTER SET|CHARSET) [LIKE 匹配的模式];
查看MySQL
中支持的比较规则:
SHOW COLLATION [LIKE 匹配的模式];
比较规则的命名规律:
比较规则名称以字符集的名称开头,后边紧跟着该比较规则主要作用于哪种语言,后缀意味着该比较规则是否区分语言中的重音、大小写等等

如: utf8_polish_ci
utf8 表示utf8字符集
polish 以波兰语的规则比较
ci 表示不区分大小写
字符集的应用
MySQL
有4个级别的字符集和比较规则:
服务器级别
数据库级别
表级别
列级别
服务器级别
MySQL
提供了两个系统变量来表示服务器级别的字符集和比较规则:
character_set_server 服务器级别的字符集
collation_server 服务器级别的比较规则
查看服务器级别的字符集和比较规则:
SHOW VARIABLES LIKE 'character_set_server';SHOW VARIABLES LIKE 'collation_server';
这两个变量的值可以在启动服务器程序时通过启动选项或者在服务器程序运行过程中使用SET
语句进行修改
数据库级别
MySQL
提供了两个系统变量来表示数据库级别的字符集和比较规则:
character_set_database 数据库级别的字符集
collation_database 数据库级别的比较规则
查看数据库的字符集和比较规则:
SHOW VARIABLES LIKE 'character_set_database';SHOW VARIABLES LIKE 'collation_database';
注意: character_set_database 和 collation_database是只读的,我们不能通过修改这两个变量的值而改变当前数据库的字符集和比较规则
在创建和修改数据库的时候可以指定该数据库的字符集和比较规则:
# 创建数据库时指定字符集和比较规则CREATE DATABASE 数据库名[[DEFAULT] CHARACTER SET 字符集名称][[DEFAULT] COLLATE 比较规则名称];# 修改数据库字符集和比较规则ALTER DATABASE 数据库名[[DEFAULT] CHARACTER SET 字符集名称][[DEFAULT] COLLATE 比较规则名称];
创建数据库时不指定字符集和比较规则,则使用服务器级别的字符集和比较规则
表级别
在创建和修改表的时候指定表的字符集和比较规则:
CREATE TABLE 表名 (列的信息)[[DEFAULT] CHARACTER SET 字符集名称][COLLATE 比较规则名称]]ALTER TABLE 表名[[DEFAULT] CHARACTER SET 字符集名称][COLLATE 比较规则名称]
如果创建和修改表的语句中没有指明字符集和比较规则,将使用该表所在数据库的字符集和比较规则
列级别
创建和修改列定义的时候可以指定该列的字符集和比较规则:
CREATE TABLE 表名(列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称],其他列...);ALTER TABLE 表名 MODIFY 列名字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];
如果在创建和修改的语句中没有指明字符集和比较规则,将使用该列所在表的字符集和比较规则,在转换列的字符集时需要注意,如果转换前列中存储的数据不能用转换后的字符集进行表示会发生错误。
由于字符集和比较规则是互相有联系的,如果修改其中一个,另一个也会跟着变化,具体规则如下:
只修改字符集,则比较规则将变为修改后的字符集默认的比较规则
只修改比较规则,则字符集将变为修改后的比较规则对应的字符集
不论哪个级别的字符集和比较规则,这两条规则都适用
客户端和服务器通信中的字符集
同一个字符串编码和解码使用的字符集不一样,可能会产生乱码
把0xE68891
这个字节串按照utf8
字符集进行解码,然后又把它按照gbk
字符集进行编码,最后编码后的字节串是0xCED2
,这个过程称为字符集的转换
MySQL中字符集的转换
MySQL从发送请求到返回结果这个过程中伴随着多次字符集的转换,这个过程中需要用到3个系统变量:
character_set_client | 服务器解码请求时使用的字符集 |
character_set_connection | 服务器处理请求时会把请求字符串从character_set_client转为 character_set_connection |
character_set_results | 服务器向客户端返回数据时使用的字符集 |
从发送请求到返回结果过程中字符集的变化过程:

1. 客户端发送请求
客户端发送请求所使用的字符集:
类
Unix
系统使用的是utf8Windows
使用的是gbk可视化工具(如navicat)可能会使用自定义的字符集,而不是操作系统默认的字符集
2. 服务器接收到客户端发送来的请求
不管客户端采用什么字符集进行编码,服务器都会使用character_set_client字符集对接受到的数据进行解码,再使用character_set_connection
字符集进行编码
3. 服务器查找数据记录
如果数据列使用的字符集和character_set_connection代表的字符集不一致,还需要进行一次字符集转换,再去数据表查找数据,得到查询结果
4. 服务器将查询结果使用character_set_results
字符集编码后返回给客户端
5. 客户端使用自身所采用的字符集解码请求结果
注意:
客户端采用的字符集与服务器
character_set_client
字符集不一致,服务器将无法正确识别并处理客户端的请求客户端采用的字符集与服务器
character_set_results
字符集不一致,客户端将无法正确识别并处理服务器返回的结果,结果为乱码character_set_connection
要注意该字符集包含的字符范围一定要涵盖请求中的字符,否则会导致有的字符无法使用character_set_connection
代表的字符集进行编码,服务器就会向用户发出一个警告
character_set_client 、character_set_connection、character_set_results 这三个系统变量设置时通常和客户端使用的字符集保持一致,减少无谓的字符集转换。
为了方便我们设置,MySQL
提供了一条非常简便的语句:
SET NAMES 字符集名;# 其效果等同于:SET character_set_client = 字符集名;SET character_set_connection = 字符集名;SET character_set_results = 字符集名;
也可以在启动客户端的时候指定default-character-set
启动选项设置这三个系统变量,效果等同于执行一遍SET NAMES utf8
比较规则的应用
比较规则
的作用通常体现在比较字符串表达式的大小以及对某个字符串列进行排序中,所以有时候也称为排序规则
。
在对字符串做比较或者对某个字符串列做排序操作时如果没有得到想象中的结果,则需要思考一下是不是比较规则
的问题




