mysql服务器设置了utf8,中文怎么还是乱码? 您所在的位置:网站首页 mysql有中文吗 mysql服务器设置了utf8,中文怎么还是乱码?

mysql服务器设置了utf8,中文怎么还是乱码?

2023-02-22 13:02| 来源: 网络整理| 查看: 265

写在前面,本文不解释什么是字符集和各种字符集的区别,各位可以自行在互联网上自己寻找答案,本文只介绍数据库查询过程中涉及到的编码相关知识

首先:

我们通过下面的语句来引入我们今天的话题

上述我们看到mysql一部分属性的字符集(这里在安装时没有做任何调整),下面我们分别解释一下:

character_set_client  //客户端字符集

character_set_connection //连接字符集

character_set_database //mysql数据库字符集

character_set_filesystem  //文件系统字符集

character_set_results  //结果集字符集

character_set_server    //服务器字符集

character_set_system  //系统字符集

当然mysql支持很多字符集,可以通过下面的语句来获取

通过上图可以看到,mysql支持的字符集达41种之多,这不是我们今天的重点,这里大家知道即可。但是我们要注意一下Default collation这个属性,它代表的是每种字符集的默认比较规则。

因为我们今天的重点在我们常用字符集utf8、utf8mb4上,所以我们看一下utf8、utf8mb4字符集的比较规则。见下图:

从上图中,我们看到utf8(utf8mb4)支持很多比较规则,一般我们都是用默认(Default=Yes)的比较规则(utf8_general_ci和utf8mb4_general_ci)

当然这个可以修改,比如将utf8mb4_general_ci修改为utf8mb4_swedish_ci,意味着将utf8mb4的通用比较规则改为瑞士语比较规则

_ci代表不区分大小写的意思,其他的还有_ai(不区分重音)、_as(区分重音)、_cs(区分大小写)、_bin(以二进制方式做比较)

正题:

上述的讲解只是为了让下面的主题更加容易理解

mysql有4个粒度不同的字符集和比较规则:

1、服务器级别

2、数据库级别

3、表级别

4、属性级别

下面作者以本机mysql环境来演示(其他环境的mysql不代表和作者演示的属性值一致)

1、服务器级别:

通过命令我们看到我的mysql服务器的字符集是latin1、比较规则是latin1_swedish_ci

2、数据库级别

我们看到数据库的字符集是utf8mb4,其比较规则也是对应的utf8mb4_general_ci

数据库的字符集不能通过修改变量来改变它,它是通过创建数据库的时候指定的、或者没有指定直接使用的服务器级别的字符集和比较规则

3、表级别

和数据库类似,表级别的字符集可以在创建的时候指定、也可以不指定,直接使用数据库级别的字符集,如下图的2种建表语句

让我们来看一下,是不是像我们说的一样:

4、属性级别

属性级别的字符集,可以在创建列或者修改列的时候来指定,同一个道理,如果没有指定则直接使用所在表的字符集和对应的比较规则

现在我们讲kuya1表的name属性的字符集改为gbk

alter table kuya1 modify name varchar(32) character set gbk collate gbk_chinese_ci;

再来看看kuya1表的字符集,可以看出表的字符集和列的不一样

编码解码过程:

在我们一条sql语句执行的过程,大概分为几个过程:

1、客户端发送请求

2、服务端接收请求

3、服务端处理请求

4、服务端生成响应

5、客户端接收响应

下面我们用实际例子来演示:

1、客户端发送请求

我们来启动一个客户端,并指定utf8字符集,意思是客户端将会用utf8字符集对请求的字符串进行编码

2、服务端接收请求

对服务端来讲,客户端发过来一串字符串,比如步骤1中的name=‘隔壁老王’,服务端怎么知道用什么编码集对‘隔壁老王’进行编码,然后进行下一步操作呢,是的就是character_set_client这个属性,你一定还记得文章开头的图

上图中是utf8、客户端连接的时候也是utf8,所以下图中是正常的

那如果我们把这个属性修改为latin1呢

这是怎么回事?暴躁啊

原因是:你客户端是utf8,但是我偏偏用latin1来编码,最终展示的当然是乱码啦,就好比两个人说话,我得知你会中文,我用中文和你聊天,结果你丫的只会拉丁文,最后鸭同鸡讲。。。

3、服务端处理请求

为了验证后续操作,我们把character_set_client改回utf8

set character_set_client='utf8';

尽管服务端对请求的字符串序列按照character_set_client的指定的编码集进行编码,但是在真正处理的时候,又会将其按照character_set_connection编码集进行编码,步骤2中,可知character_set_connection=utf8,我们将其修改为latin1,进行验证一下

4、服务端生成响应

为了验证后续操作,我们把character_set_connection改回utf8

set character_set_connection='utf8';

通过上面得知,我们知道客户端对‘隔壁老王’这条记录是用utf8发送,服务端用utf8进行接收,并且用utf8进行处理,那查询出来的时候,一定能正常返回吗?

我们在做一下实验

大家看到了,‘隔壁老王’记录,返回的是????,隔壁老黄返回的是正常数据,为什么呢?好奇怪!

其实也不奇怪,返回数据是要按照属性character_set_results进行再次编码的,然后再返回给客户端的,所以‘隔壁老王’、'隔壁老刘'都不是按照latin1进行编码保存的,只有'隔壁老黄'是latin1字符集编码保存的,所以出现了上面的情况。

5、客户端接收响应

对步骤4来讲,‘隔壁老黄’能正常显示,最终还是因为character_set_results和客户端启动时default-character-set编码值一致,如果不一致,也会有问题,如果不指定default-character-set,取决于操作系统当前使用的字符集。

首发自:https://www.kuya123.com/2021/06/14-mysql-charset



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有