什么是字符集
众所周知在我们的计算机中存储的是二进制即01的数字,是没有有字符的。那么如何存储字符串呢?就是将特定的二进制数与字符进行映射。0000001—>a
这里我们将1与字符a进行映射,那么计算机在看到1的时候就知道要显示a了。多个特定的映射关系组成的集合就是字符集。
将字符映射成二级制数据的过程成为编码,而将二进制映射成字符的过程成为解码。
重要的字符集
字符集 | 描述 |
---|---|
ASCII | 128个字符,使用一个字节来表示字符 |
ISO8859-1(Latin1) | 256个字符,在ASCII的基础上进行扩充,使用一个字节来表示字符 |
GB2312 | 收录了汉字6763个,兼容ASCII,如果是ASCII的字符则一个字节反之两个字节(变长编码方式中,最高位为1表示是一个字符的部分,ASCII最高位为0) |
GBK | 扩充GB2312 |
UTF-8 | 几乎包括所有的字符,兼容ASCII,边长编码,1~4个字节表示一个字符 |
因为我们较长使用的是13个字节的字符,所以在MySQL中有所优化。utf8mb3使用的是13个字节的字符,是正版utf-8的阉割版,在MySQL中utf-8即为utf8mb3.如果要使用四个字节表示的字符如emoj表情则需要使用utf8mb4;
查看字符集
show (CHARACTER SET|CHARSET) [like 匹配模式]
show charset; #mysql一共支持41种字符集
charset:字符集名称
Description:描述
Default collation:默认比较规则
Maxlen:描述字符的最大字节数
+----------+---------------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+---------------------------------+---------------------+--------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| dec8 | DEC West European | dec8_swedish_ci | 1 |
| cp850 | DOS West European | cp850_general_ci | 1 |
| hp8 | HP West European | hp8_english_ci | 1 |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci | 1 |
| latin1 | cp1252 West European | latin1_swedish_ci | 1 |
......
| gb18030 | China National Standard GB18030 | gb18030_chinese_ci | 4 |
+----------+---------------------------------+---------------------+--------+
41 rows in set (0.08 sec)
常用字符集的Maxlen
字符集名称 | Maxlen |
---|---|
ascii | 1 |
latin1 | 1 |
gb2312 | 2 |
gbk | 2 |
utf8 | 3 |
utf8mb4 | 4 |
查看比较规则
show collation [like 匹配模式]
show collation like 'utf8\_%';
+--------------------------+---------+-----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+--------------------------+---------+-----+---------+----------+---------+
| utf8_general_ci | utf8 | 33 | Yes | Yes | 1 |
| utf8_bin | utf8 | 83 | | Yes | 1 |
| utf8_unicode_ci | utf8 | 192 | | Yes | 8 |
......
| utf8_vietnamese_ci | utf8 | 215 | | Yes | 8 |
| utf8_general_mysql500_ci | utf8 | 223 | | Yes | 1 |
+--------------------------+---------+-----+---------+----------+---------+
27 rows in set (0.06 sec)
utf8_general_ci
- utf8:表示什么字符集的比较规则
- genral:表示比较规则所应用的语言,general表示通用比较规则
- ci:表示比较规则是否区分重音,大小等
后缀 | 英文释义 | 描述 |
---|---|---|
_ai | accent insensitive | 不区分重音 |
_as | accent sensitive | 区分重音 |
_ci | case insensitive | 不区分大小写 |
_cs | case sensitive | 区分大小写 |
_bin | binary | 以二进制方式比较 |
各个级别的字符集比较规则
MySQL一共有四种比较级别:服务器级别,数据库级别,表级别,列级别
数据库级别
MySQL提供了两个系统变量来描述服务器级别的字符集和比较规则。
系统变量 | 描述 |
---|---|
character_set_server | 服务器级别的字符 |
collation_server | 服务器级别的比较规则 |
show variables like 'character_set_server';
+----------------------+--------+
| Variable_name | Value |
+----------------------+--------+
| character_set_server | latin1 |
+----------------------+--------+
show variables like 'collation_server';
+------------------+-------------------+
| Variable_name | Value |
+------------------+-------------------+
| collation_server | latin1_swedish_ci |
+------------------+-------------------+
修改字符和比较规则
[server]
character_set_server=gb2312
collation_server=gb2312_chinese_ci
数据库级别
系统变量 | 描述 |
---|---|
character_set_databses | 数据库级别的字符集 |
collation_server | 数据库级别的比较规则 |
show variables like 'character_set_database';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| character_set_database | utf8 |
+------------------------+-------+
show variables like 'collation_database';
+--------------------+-----------------+
| Variable_name | Value |
+--------------------+-----------------+
| collation_database | utf8_general_ci |
+--------------------+-----------------+
修改比较规则
创建表的时候选择字符集和比较规则。当我们没有指定的时候默认使用的是服务器级别的比较规则。
create database test
-> character set gb2312
-> collate gb2312_chinese_ci;
表级别
没有指定默认为数据库级别
create table test01(
-> id int
-> )character set utf8 collate utf8_general_ci;
列级别
创建的时候没有声明则默认使用表级别
alter table test01 modify name varchar(10) character set gbk collate gbk_chinese_ci;
小结
- 如果创建或修改列的时候没有显示指定则默认使用表级别
- 创建表的时候没有指定则默认使用数据库级别的
- 创建数据库没有使用则默认使用服务器级别
- 只修改字符集则比较规则变成该字符集默认比较规则
- 只修改比较规则则变成对应的字符集
客户端和服务端使用字符集
字符的本质实际上就是字节序列,计算机根据字符集将字节码映射成字符。字符在网络都是转成字节码进行传输的。那么在如果客户端和服务端使用的字符集不同,那么就会出现乱码的情况。
客户端
客户端一般使用的是操作系统的默认字符集。不过在启动mysql客户端的时候可以自定义对应的字符集
mysql --default-cahracter-set=utf8#客户端会以utf-8字符集对请求的字符串进行编码
服务端
服务端在接受的客户端的Mysql请求字节序列后,会将其看作是character_set_client
代表的字节序列(这个系统变量是session级别的)在处理请求的时候又会将其转换成使用session级别的characcter_set_connection
对应的字符集进行编码的字节序列。
对与connection系统变量的理解:在sql语句中并不都是和表种的字段相关的有可能出现selecct 'a'='A'
这种语句,这个时候server服务器只不过能根据clinet系统变量正确识别该语句,但是不知道使用什么比较规则,自然也就无法判断TRUE/FALSE.
select * from tt where t="我"
当出现字符和列进行比较的时候。如果两者的编码方式不同则将字符转换成列的编码方式再进行比较。
当我们需要返回数据的时候数据将被转换成character_set_reaults
session系统变量设置的字符集编码的字节序列然后发送,
系统变量(seesion) | 描述 |
---|---|
character_set_client | 服务器认为该请求是按照系统变量指定的字符集进行编码的 |
character_set_connection | 服务器在处理请求的时候会先将字节序列从client转换成connection |
collation_connection | 服务器处理请求的时候使用的比较规则 |
character_set_results | 服务器采用该系统变量指定字符集对返回给客户端的字符串进行编码 |
修改
在mysql连接成功后可以使用set语句进行修改
set names charset_name;
=
set character_set_client=charset_name;
set character_set_connection=charset_name;
set character_set_results=charset_name;