当你使用 MySQL 的

select char_length()

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

1个中文字=3个字符

的情况,

举例如下:

MySQL 查找有三级城市的省份 mysql查询名字为三个字_数据库

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

mysql> show variables like '%char%';

MySQL 查找有三级城市的省份 mysql查询名字为三个字_数据库_02


可以看到,server 使用的是 utf8 字符集,

client 使用的是 Latin1 字符集,而你使用的 secureCRT 使用的字符集 一定不是 Latin1 字符集,查看 secureCRT 使用了什么字符集的操作步骤:

MySQL 查找有三级城市的省份 mysql查询名字为三个字_服务器_03

MySQL 查找有三级城市的省份 mysql查询名字为三个字_MySQL_04


上图可见,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 查找有三级城市的省份 mysql查询名字为三个字_MySQL 查找有三级城市的省份_05

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

mysql> show variables like '%char%';

MySQL 查找有三级城市的省份 mysql查询名字为三个字_服务器_06


没问题,接下来,测试 char_length(),

mysql> select char_length('韩');

MySQL 查找有三级城市的省份 mysql查询名字为三个字_mysql_07

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

mysql> show variables like '%char%';

MySQL 查找有三级城市的省份 mysql查询名字为三个字_MySQL_08


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

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

命令如下:

mysql> set character_set_results=utf8;

MySQL 查找有三级城市的省份 mysql查询名字为三个字_mysql_09

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

mysql> show variables like '%char%';

MySQL 查找有三级城市的省份 mysql查询名字为三个字_服务器_10

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

mysql> select char_length('韩');

MySQL 查找有三级城市的省份 mysql查询名字为三个字_MySQL 查找有三级城市的省份_11

结果无误,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%';

MySQL 查找有三级城市的省份 mysql查询名字为三个字_服务器_12


上图中,我们关注的两个字符集,

**character_set_client **

**character_set_results **

两个都是 Latin1 字符集,

我们接下来,就是 要通过 编辑 Linuxmy.cnf 文件 ,将上述两个我们需要用到的字符集更改成 utf8 并保存使之永久生效。

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

MySQL 查找有三级城市的省份 mysql查询名字为三个字_mysql_13

进入 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_14


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

停止 MySQL 服务

[root@localhost ~]# service mysqld stop

请注意,命令中是 myslqd 而不是 myslql

MySQL 查找有三级城市的省份 mysql查询名字为三个字_mysql_15


启动 MySQL 服务

[root@localhost ~]# service mysqld start

MySQL 查找有三级城市的省份 mysql查询名字为三个字_MySQL 查找有三级城市的省份_16


进入 MySQL

[root@localhost ~]# mysql

查看 MySQL 的 字符集

mysql> show variables like '%char%';

MySQL 查找有三级城市的省份 mysql查询名字为三个字_服务器_17

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

做实验,验证结果,

mysql> select char_length('韩');

MySQL 查找有三级城市的省份 mysql查询名字为三个字_MySQL 查找有三级城市的省份_18


没问题,汉字显示正确,字符个数识别正确,1 个汉字是 1 个字符。

即便将安装有 MySQLLinux 关机重启,我们对 MySQL 的字符集的设置依然有效,永久不变。

January the 07th 2022 Thursday