【MySQL(九)】字符集

编码:字符 -> 二进制;

解码:二进制 -> 字符;

为什么会出现乱码?因为编码和解码的规则不同。本质上都是同样的一串二进制流,按照不同的规则解读的结果当然是不同的。类比一下我们的时间戳转时间的场景,时间戳就好比是二进制,时区就好比是不同的字符集,同一个时间戳用不同的时区转换,得到的结果当然是不同的。所以,我们只要保证编码和解码用同一套字符集就不会出现乱码了。

mysql里支持的字符集

这里主要指存储数据的字符集。可以使用如下命令查看:

show charset

另外我们可以设置不同级别的字符集,服务器、数据库、表、列四个级别。

存储不同字符集的数据,消耗的空间是不同的。比如ascii字符集,就是固定一个字节。但是对于utf8字符集,需要1-3个字节,这是变长字符集,所以空间是不固定的。

mysql中utf8其实指的是utf8mb3字符集,是mysql里的一种原始utf8字符集的变种,原始的utf8字符集需要1-4字节,而utf8mb3只需要1-3字节。原始的utf8字符集在mysql里叫utf8mb4。

字符集转换

在客户端发起一条sql语句,到接受服务端返回,这个过程中的字符集是如何转换的?

1.客户端使用mysql client发起sql语句查询,此时在客户端机器上,使用操作系统的字符集对命令进行了编码,转成了二进制流发送到网络中;

2.mysql服务端接受二进制流,使用character_set_client指定的字符集解码二进制流;

3.将字符流使用character_set_connection指定的字符集转换;

4.将字符集与列数据作比较;

5.将结果使用character_set_results指定的字符集编码,返回给客户端;

这里有个问题,为什么需要转成character_set_connection?
https://stackoverflow.com/questions/16082480/what-is-the-purpose-of-character-set-connection
这里有一段解释。意思是在做字符常量比较时,需要使用character_set_connection对常量进行转换。啥意思?

比如select * from text where name = '哈哈'这条语句。服务端首先会用character_set_client解码,然后处理语句。里面的where查询中的name列,会按照该列对应的字符集转码,但是对于常量‘哈哈’怎么处理?显然如果不处理,那么会按照character_set_client处理,但这可能有问题啊,可能会导致参与比较的双方使用的字符集都不一样,这还怎么比?所以就需要再按照character_set_connection来转换一次常量,所以character_set_connection貌似应该与比较的列名的字符集一致。

这里有三种字符集需要设置?其实可以只用如下命令:

set names xxx

便可以同时设定如上三个字符集。

 

几个例子:

默认都是utf8编码。

create table text (
    name varchar(10)
) engine=Innodb default charset=utf8;

mysql> insert into text values('我');
Query OK, 1 row affected (0.01 sec)

建表并插入一条数据;

mysql> set character_set_results=gbk;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from text;
+------+
| name |
+------+
| ��     |
+------+
1 row in set (0.00 sec)

这里设置了character_set_results为不同的编码,导致查询结果乱码;

 

mysql> set character_set_connection = ascii;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from text where name = '我';
Empty set, 1 warning (0.00 sec)

这是设置了character_set_connection,导致无法查到数据;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值