当你使用 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 文件一致就好,可以认为 Linux 的 my.cnf 和 Windows 的 my.ini ,就是同一个文件,可以互换使用,在 不同的操作系统中用不同的名字做同样的工作,什么内容都不用动,放到 Linux 中 起名叫 my.cnf,放到 Windows 中 起名叫 my.ini ,能起到相同的作用,
再用命令看一遍,当前 MySQL 的字符集,
mysql> show variables like '%char%';
上图中,我们关注的两个字符集,
**character_set_client **
**character_set_results **
两个都是 Latin1 字符集,
我们接下来,就是 要通过 编辑 Linux 的 my.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 个字符。
即便将安装有 MySQL 的 Linux 关机重启,我们对 MySQL 的字符集的设置依然有效,永久不变。
January the 07th 2022 Thursday