关于MySQL中 select char_length() 1个中文字等于3个字符的问题

当你使用 MySQL 的

select char_length()

查看一串汉字有几个字符的时候,也许会出现,

1个中文字=3个字符

的情况,
举例如下:
在这里插入图片描述

这种,情况,一般都是由于你使用了 secureCRT 这类远程登录软件去远程访问 装在 Linux 里的 MySQL 造成的,
原因是,secureCRT 去远程登录 MySQL 的时候,相当于是 MySQL 的 客户端 client ,
所以,当客户端的字符集,与服务器字的字符集,不一致的时候,就会出现上面,char_length()查询中文字的结果出现, 1 个汉字等于 3 个字符的情况。
接下来,先确认一下,客户端 client 和服务端 server 都使用的是什么样的字符集,

mysql> show variables like '%char%';

在这里插入图片描述
可以看到,server 使用的是 utf8 字符集,
client 使用的是 Latin1 字符集,

而你使用的 secureCRT 使用的字符集 一定不是 Latin1 字符集,查看 secureCRT 使用了什么字符集的操作步骤:
在这里插入图片描述在这里插入图片描述
上图可见,secureCRT 使用的字符集是 utf8,
utf8 字符集,存储一个汉字使用 3 个字节,
那么问题就出现了,
utf8 字符集中,1 个中文字,虽然占用 3 个字节,但却被看作是 1 个字符,

所以,在使用了 secureCRT 去连接 MySQL 的时候,
secureCRT 会按 utf8 字符集的规则 将一个汉字 存储进 3 个字节里面,准备传给 MySQL

然后,在与 MySQL 通信时,又得知 MySQL 要求它的客户端 client 要使用 Latin1 字符集,

所以,secureCRT 将 3 个字节的信息 转成 Latin1 字符集,
Latin1 字符集 是识别不了汉字的,
Latin1 字符集, 是,单字节字符集,一个字符占用 一个字节,反过来,一个字节就是一个字符,
所以,虽然 Latin1 字符集并不认识这个汉字,但被存储在 3个字节中的汉字,在Latin1 字符集看来,就只是3个字节,即 3 个字符,
所以,以 Latin1 字符集, 传输到 MySQL ,使用命令 select char_length(‘中文’)的时候,
得到 的结果,3倍于 utf8 字符集下 使用 select char_length(‘中文’) 得到的字符数。

因此,要解决这个问题,就要让 MySQL 的 客户端 client 也使用 utf8 字符集,这样,就不需要在 Latin1 字符集中去理解汉字了。

进入 MySQL ,设置 MySQL 字符集,
使用的命令如下:

mysql> set character_set_client=utf8;

在这里插入图片描述

接下来再查看 MySQL 的 客户端 client 字符集 ,是否变成了 utf8

mysql> show variables like '%char%';

在这里插入图片描述
没问题,接下来,测试 char_length(),

mysql> select char_length('韩');

在这里插入图片描述

可以看出,查询的结果变成了,一个汉字是一个字符的,正确的情况,
但,又出现了新的情况,就是,在回显的结果中,汉字的位置 变成了问号,这说明,汉字被 MySQL 正确识别了(因为,1 个汉字被认出来是 1 个字符,这个结果就能说明 MySQL 正确的识别了汉字,)
但显示的结果中,却将汉字显示成了问号”?“,这是典型的乱码情况,
为什么会出现,乱码呢,原因就在 MySQL 的结果集( character_set_results )使用了不理解中文的字符集,所以,在给用户回显的信息里,就出现了乱码。
用命令看一下吧,

mysql> show variables like '%char%';

在这里插入图片描述
可以看到,MySQL 的 回显结果集( character_set_results) 也使用了不能理解中文的 Latin1 字符集,所以,虽然 MySQL 正确识别了 它的客户端 client, secureCRT 送来的中文字符,并正确的判断出了中文字符的个数,但在回显给用户的时候,因为使用了 Latin1 字符集,导致回显过程中无法显示中文,因此出现了将汉字显示成问号 ”“ ,即出现了乱码的情况。

所以,为了解决所有的问题,我们还需要再将 MySQL 的结果集 ( character_set_results)进行设置,使其变成 utf8 字符集。

命令如下:

mysql> set character_set_results=utf8;

在这里插入图片描述

再次查看,MySQL 使用的 字符集,

mysql> show variables like '%char%';

在这里插入图片描述

两个,我们曾经做过更改的字符集 ,(character_set_client)和( character_set_results)都已经变成了 utf8 字符集。
再做实验,进行验证,

mysql> select char_length('韩');

在这里插入图片描述

结果无误,1 个中文字等于 1 个字符,结果里中文显示的也正确,

但,这么做,还是没有完全解决问题,
因为,现在,对 MySQL 的修改都只在当前有效,一旦 MySQL 重新启动后,刚才更改的几处又会变回到原来的 Latin1 字符集,即当前的配置在 MySQL 重启后失效。

所以,我们最后还需要,将,更改的 几处 MySQL 字符集 结果永久写进 MySQL 中去。

方法是,在 Linux 中 编辑 /etc/my.cnf 文件,

注:

如果你是 Windows 系统,就去 MySQL 的安装路径(也就是 mysqld.exe 应用程序 【请注意这里是 mysqld 不是 mysql】 所在的路径)中找 my.ini 文件,编辑的内容和 Linux 系统中的 /etc/my.cnf 文件一致就好,可以认为 Linuxmy.cnfWindowsmy.ini ,就是同一个文件,可以互换使用,在 不同的操作系统中用不同的名字做同样的工作,什么内容都不用动,放到 Linux 中 起名叫 my.cnf,放到 Windows 中 起名叫 my.ini ,能起到相同的作用,

再用命令看一遍,当前 MySQL 的字符集,

mysql> show variables like '%char%';

在这里插入图片描述
上图中,我们关注的两个字符集,
**character_set_client **
**character_set_results **
两个都是 Latin1 字符集,
我们接下来,就是 要通过 编辑 Linuxmy.cnf 文件 ,将上述两个我们需要用到的字符集更改成 utf8 并保存使之永久生效。

[root@localhost ~]# vim /etc/my.cnf

在这里插入图片描述

进入 my.cnf 文件,按下键盘上的 i 键,进入编辑模式,在 [mysqld] 上边加入,红框内的命令,

[client]
default-character-set=utf8

如果,[client] 已存在,就只加入 default-character-set=utf8
如果,**[client]**不存在,就两条语句都写入
按下键盘上的 Esc 键,进入保存模式,
再按下键盘上的组合键 shift + :
接着连续按键盘上的 w q 两个按键,完成 my.cnf 文件的保存工作,回到 Linux 系统中。

在这里插入图片描述
这时,进入 MySQL 查看 字符集,是没有变化的,需要停止并重新启动 MySQL 服务 才能生效。

停止 MySQL 服务

[root@localhost ~]# service mysqld stop

请注意,命令中是 myslqd 而不是 myslql
在这里插入图片描述
启动 MySQL 服务

[root@localhost ~]# service mysqld start

在这里插入图片描述
进入 MySQL

[root@localhost ~]# mysql

查看 MySQL 的 字符集

mysql> show variables like '%char%';

在这里插入图片描述

可以看到,我们需要的 两个 字符集 都已经变成 utf8 了,成功,
| character_set_client | utf8
| character_set_results | utf8

做实验,验证结果,

 mysql> select char_length('韩');

在这里插入图片描述
没问题,汉字显示正确,字符个数识别正确,1 个汉字是 1 个字符。
即便将安装有 MySQLLinux 关机重启,我们对 MySQL 的字符集的设置依然有效,永久不变。

January the 07th 2022 Thursday

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值