您的当前位置:首页正文

MySQL 乱码之我见

2023-11-09 来源:要发发知识网

先着重介绍一下mysql的字符集,这样能对产生mysql的根源有一个了解。mysql 的字符集支持有两个方面:字符集(Character set)和排序方式(Collation)。另外对于字符集的支持细化到四个层次: 服务器(server),数据库(database),数据表(table)和连接(connection)。

连上mysql 后使用status 命令,可以看到类似如下输出:

>mysql statusConnection id:          305Current database:Current user:           root@localhostSSL:                    Not in useCurrent pager:          stdoutUsing outfile:          ‘‘Using delimiter:        ;Server version:         5.6.23 MySQL Community Server (GPL)Protocol version:       10Connection:             Localhost via UNIX socketServer characterset:    utf8Db     characterset:    utf8Client characterset:    utf8Conn.  characterset:    utf8

Server characterset 就是mysql默认字符集,当创建数据库没有指定字符集时数据库就采用此默认值。可以在mysql的配置文件中的 mysqld 段中对此值进行修改

[mysqld]port        = 3306socket      = /tmp/mysql.sockcharacter-set-server = utf8collation-server = utf8_general_ci

Db characterset:是当前数据库默认的字符集,当创建表时没有指定字符集,此表就使用当前默认值。例如创建一个 db_test 数据库,字符集使用 latin1

CREATE DATABASE `db_test` CHARACTER SET ‘latin1‘ COLLATE ‘latin1_swedish_ci‘;use db_test;

然后再使用 status 命令,可以看到这个时候 Db characterset 变为 latin1 了

>mysql statusConnection id:          305Current database:       db_testCurrent user:           root@localhostSSL:                    Not in useCurrent pager:          stdoutUsing outfile:          ‘‘Using delimiter:        ;Server version:         5.6.23 MySQL Community Server (GPL)Protocol version:       10Connection:             Localhost via UNIX socketServer characterset:    utf8Db     characterset:    latin1Client characterset:    utf8Conn.  characterset:    utf8

在数据库中分别创建两种表 test1 和 test2,其中 test1 使用默认字符集, test2 指定字符集为GBK

create table test1 (name varchar(20));create table test2 (name varchar(20)) default charset=GBK;

使用 show create table 命令查看上述两张表,可以看到 test1 使用了当前数据库的默认字符集latin1,而test2使用的字符集是GBK。

mysql> show create table test1;+-------+-------------------------------------------------------------------------------------------------+| Table | Create Table                                                                                    |+-------+-------------------------------------------------------------------------------------------------+| test1 | CREATE TABLE `test1` (  `name` varchar(20) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1 |+-------+-------------------------------------------------------------------------------------------------+mysql> show create table test2;+-------+----------------------------------------------------------------------------------------------+| Table | Create Table                                                                                 |+-------+----------------------------------------------------------------------------------------------+| test2 | CREATE TABLE `test2` (  `name` varchar(20) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=gbk |+-------+----------------------------------------------------------------------------------------------+

mysql 存储信息最终是已二进制的形式来存储的。所以在存储之前就需要对信息进行编码,同时从数据库读取信息后需要解码。具体使用那种编码、解码方式就是根据Client characterset以及表对应的字符集,如果没有显示的指定,那么会有一个默认值。当使用命令行的方式连接mysql,可以在mysql 配置中 mysql 段来指定默认Client characterset。例如:

[client]port        = 3306socket      = /tmp/mysql.sockdefault-character-set   = utf8

也可以使用在连接时候指定

mysql -uroot -p --default-character-set=utf8

另外在登录mysql 后也可以使用 set names 来指定

set names utf8

关于优先级,set names utf8 最高,mysql -uroot -p --default-character-set=utf8 其次、my.cnf 最后。

上面对字符集做了一个简单的介绍,建议大家也把上面的mysql 命令试一下,这样理解或更加深刻。现在再来说一下乱码的情况,一般出现乱码就是因为字符集(编码)不同,换句话说就是当字符集(编码)一致时就不会出现乱码。前面介绍了一下字符集,所以知道了好几种,那到底是需要什么字符集一致呢?答案是:Client characterset 与 数据库表的字符集。 下面还是通过例子来说明,使用上面创建的表 test1。

由于test1使用的字符集是 latin1,那么使用下面的方式连上mysql

mysql -uroot -p  db_test --default-character-set=latin1

再次确认一下Client characterset 与 数据库表的字符集

mysql> status--------------mysql  Ver 14.14 Distrib 5.6.23, for osx10.8 (x86_64) using  EditLine wrapperConnection id:          310Current database:       db_testCurrent user:           root@localhostSSL:                    Not in useCurrent pager:          stdoutUsing outfile:          ‘‘Using delimiter:        ;Server version:         5.6.23 MySQL Community Server (GPL)Protocol version:       10Connection:             Localhost via UNIX socketServer characterset:    utf8Db     characterset:    latin1Client characterset:    latin1Conn.  characterset:    latin1-------------------------mysql> show create table test1;+-------+-------------------------------------------------------------------------------------------------+| Table | Create Table                                                                                    |+-------+-------------------------------------------------------------------------------------------------+| test1 | CREATE TABLE `test1` (  `name` varchar(20) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1 |+-------+-------------------------------------------------------------------------------------------------+

可以看到Client characterset与表的字符集是一致的,然后插入一条含有中文的记录,同时查询看看。

mysql> insert into test1(name) values(‘中test文1234测试‘);mysql> select * from test1;+----------------------+| name                 |+----------------------+| 中test文1234测试 |+----------------------+

现在证明当Client characterset与表的字符集一致时,没有出现乱码。那现在使用set names 来修改一下 Client characterset 看看效果。

mysql> set names utf8;Query OK, 0 rows affected (0.00 sec)mysql> status--------------mysql  Ver 14.14 Distrib 5.6.23, for osx10.8 (x86_64) using  EditLine wrapperConnection id:          310Current database:       db_testCurrent user:           root@localhostSSL:                    Not in useCurrent pager:          stdoutUsing outfile:          ‘‘Using delimiter:        ;Server version:         5.6.23 MySQL Community Server (GPL)Protocol version:       10Connection:             Localhost via UNIX socketServer characterset:    utf8Db     characterset:    latin1Client characterset:    utf8Conn.  characterset:    utf8mysql> select * from test1;+--------------------------------------+| name                                 |+--------------------------------------+| ??-test?–?1234?μ?èˉ? |+--------------------------------------+

utf8 出现乱码,再试试gbk

mysql> set names gbk;Query OK, 0 rows affected (0.00 sec)mysql> status--------------mysql  Ver 14.14 Distrib 5.6.23, for osx10.8 (x86_64) using  EditLine wrapperConnection id:          310Current database:       db_testCurrent user:           root@localhostSSL:                    Not in useCurrent pager:          stdoutUsing outfile:          ‘‘Using delimiter:        ;Server version:         5.6.23 MySQL Community Server (GPL)Protocol version:       10Connection:             Localhost via UNIX socketServer characterset:    utf8Db     characterset:    latin1Client characterset:    gbkConn.  characterset:    gbkmysql> select * from test1;+------------------------+| name                   |+------------------------+| ???test?1234???? |+------------------------+

上面把Client characterset 设置分别设置为 utf8 或 GBK 后,然后查询都出现了乱码,而且乱码显示还不一样。下面再测试一样不同Client characterset字符集先插入在读取的情况。

mysql -uroot -p  db_test --default-character-set=utf8 mysql> status--------------mysql  Ver 14.14 Distrib 5.6.23, for osx10.8 (x86_64) using  EditLine wrapperConnection id:          312Current database:       db_testCurrent user:           root@localhostSSL:                    Not in useCurrent pager:          stdoutUsing outfile:          ‘‘Using delimiter:        ;Server version:         5.6.23 MySQL Community Server (GPL)Protocol version:       10Connection:             Localhost via UNIX socketServer characterset:    utf8Db     characterset:    latin1Client characterset:    utf8Conn.  characterset:    utf8mysql> truncate table test1;Query OK, 0 rows affected (0.01 sec)mysql> select * from test1;Empty set (0.00 sec)mysql> insert into test1(name) values(‘中test文1234测试‘);                                                                                                                                             Query OK, 1 row affected, 1 warning (0.00 sec)mysql> select * from test1;+--------------+| name         |+--------------+| ?test?1234?? |+--------------+

上面的例子说明当字符集不一致出现乱码了。 如果再把Client characterset 修改为和数据库表一致,然后看看刚刚插入的记录是否还是显示乱码

mysql> set names latin1;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;+--------------+| name         |+--------------+| ?test?1234?? |+--------------+1 row in set (0.00 sec)

还是乱码,也就是通过字符集设置也无法把乱码还原了。

通过上面这些例子可以得出结论,只有当Client characterset与表的字符集一致才不会出现乱码。

MySQL 乱码之我见

标签:

小编还为您整理了以下内容,可能对您也有帮助:

MySQL乱码的几种原因

MySQL之所以会乱码,无非是以下几种原因: 1、存进数据库之前就乱码 2、在存进数据库过程中乱码 3、存进数据库后乱码 想知道在哪

MySQL之所以会乱码,无非是以下几种原因:

1、存进数据库之前就乱码

2、在存进数据库过程中乱码

3、存进数据库后乱码

想知道在哪里出现乱码很简单,在后台打印一下就知道了。

既然知道问题出在哪里,那解决方法也很简单:

1、jsp设置编码是utf-8,保证传到后台的是utf-8的编码

2、在数据库连接上加这么一段jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8,保证传输过程是utf-8的。

3、设置数据库的编码为utf-8,在my.ini设置或者在Config设置也行,,注意的是my.ini里default-character-set要改两处地方

4、url或者easyui乱码,可以试一下将tomcat的server.xml中的

改为

要保证不乱码,首先要做到编码要统一,其他问题都好找出来。完。

本文永久更新链接地址:

关于Mysql中文乱码问题该如何解决(乱码问题完美解决方案)



最近两天做项目总是被乱码问题困扰着,这不刚把mysql中文乱码问题解决了,下面小编把我的解决方案分享给大家,供大家参考,也方便以后自己查阅。

首先:

用show variables like “%colla%”;show varables like “%char%”;这两条命令查看数据库与服务端的字符集设置

如果查看出来都是gbk2312,或 gbk,那么就只能支持简体中文,繁体和一些特殊符号是不能插入的,我们只有修改字符集为UTF-8,

修改方法如下:

用记事本或UitraEdit打开mysql数据库安装目录下的my.ini文件打开, 然后Ctrl+F搜索default-character-set,将后面的字符集修改为UTF8,注意要修改两个地方,一个事客户端的,一个是服务端的。

然后保存,重启mysql服务、、进去继续用show variables like “%colla%”;show varables like “%char%”;着两条语句查询一下字符集。 如图:



到此就配置完成了。

注意:

如果以前建有数据库没有删除的 请用 show database 数据库名;和 show create table 表名;查看一下数据库和表的字符集是否为UTF8 , 因为修改my.ini文件,它不能修改原来数据库的的字符集。在命令行下面可以用

alter database 数据库名 character set “字符集”; 命令来修改数据库字符集

还有一点要注意的是,修改为UTF8以后,在命令行下面中文是乱码的,只输出到页面或控制台是正常的,这个问题我也上网查了一下,貌似命令行下面不支持UTF8,我也不太清楚。

当修改以后,在命令行下面如果要插入中文,可以在插入语句之前执行,set names gbk2312;就可以插入中文了,但是不能插入繁体和一些特殊符号。

关于Mysql中文乱码问题该如何解决(乱码问题完美解决方案)



最近两天做项目总是被乱码问题困扰着,这不刚把mysql中文乱码问题解决了,下面小编把我的解决方案分享给大家,供大家参考,也方便以后自己查阅。

首先:

用show variables like “%colla%”;show varables like “%char%”;这两条命令查看数据库与服务端的字符集设置

如果查看出来都是gbk2312,或 gbk,那么就只能支持简体中文,繁体和一些特殊符号是不能插入的,我们只有修改字符集为UTF-8,

修改方法如下:

用记事本或UitraEdit打开mysql数据库安装目录下的my.ini文件打开, 然后Ctrl+F搜索default-character-set,将后面的字符集修改为UTF8,注意要修改两个地方,一个事客户端的,一个是服务端的。

然后保存,重启mysql服务、、进去继续用show variables like “%colla%”;show varables like “%char%”;着两条语句查询一下字符集。 如图:



到此就配置完成了。

注意:

如果以前建有数据库没有删除的 请用 show database 数据库名;和 show create table 表名;查看一下数据库和表的字符集是否为UTF8 , 因为修改my.ini文件,它不能修改原来数据库的的字符集。在命令行下面可以用

alter database 数据库名 character set “字符集”; 命令来修改数据库字符集

还有一点要注意的是,修改为UTF8以后,在命令行下面中文是乱码的,只输出到页面或控制台是正常的,这个问题我也上网查了一下,貌似命令行下面不支持UTF8,我也不太清楚。

当修改以后,在命令行下面如果要插入中文,可以在插入语句之前执行,set names gbk2312;就可以插入中文了,但是不能插入繁体和一些特殊符号。

如何解决MySQL字符集乱码问题

一、转码失败

在数据写入到表的过程中转码失败,数据库端也没有进行恰当的处理,导致存放在表里的数据乱码。

针对这种情况,前几篇文章介绍过客户端发送请求到服务端。

其中任意一个编码不一致,都会导致表里的数据存入不正确的编码而产生乱码。

比如下面简单一条语句:

set @a = "文本字符串";

insert into t1 values(@a);

1. 变量 @a 的字符编码是由参数 CHARACTER_SET_CLIENT 决定的,假设此时编码为 A,也就是变量 @a 的编码。

2. 写入语句在发送到 MySQL 服务端之前的编码由 CHARACTER_SET_CONNECTION 决定,假设此时编码为 B。

3. 经过 MySQL 一系列词法,语法解析等处理后,写入到表 t1,表 t1 的编码为 C。

那这里编码 A、编码 B、编码 C 如果不兼容,写入的数据就直接乱码。

二、客户端乱码

表数据正常,但是客户端展示后出现乱码。

这一类场景,指的是从 MySQL 表里拿数据出来返回到客户端,MySQL 里的数据本身没有问题。客户端发送请求到 MySQL,表的编码为 D,从 MySQL 拿到记录结果传输到客户端,此时记录编码为 E(CHARACTER_SET_RESULTS)。

那以上编码 E 和 D 如果不兼容,检索出来的数据就看起来乱码了。但是由于数据本身没有被破坏,所以换个兼容的编码就可以获取正确的结果。

这一类又分为以下三个不同的小类:

1)字段编码和表一致,客户端是不同的编码

比如下面例子, 表数据的编码是 utf8mb4,而 SESSION 1 发起的连接编码为 gbk。那由于编码不兼容,检索出来的数据肯定为乱码。

2)表编码和客户端的编码一致,但是记录之间编码存在不一致的情形

比如表编码是 utf8mb4,应用端编码也是 utf8mb4,但是表里的数据可能一半编码是 utf8mb4,另外一半是 gbk。那么此时表的数据也是正常的,不过此时采用哪种编码都读不到所有完整的数据。这样数据产生的原因很多,比如其中一种可能性就是表编码多次变更而且每次变更不彻底导致(变更不彻底,我之前的篇章里有介绍)。举个例子,表 t3 的编码之前是 utf8mb4,现在是 gbk,而且两次编码期间都被写入了正常的数据。

3)每个字段的编码不一致,导致乱码

和第二点一样的场景。不同的是:非记录间的编码不统一,而是每个字段编码不统一。举个例子,表 c1 字段 a1,a2。a1 编码 gbk,a2 编码是 utf8mb4。那每个字段单独读出来数据是完整的,但是所有字段一起读出来,数据总会有一部分乱码。

三、LATIN1

还有一种情形就是以 LATIN1 的编码存储数据

估计大家都知道字符集 LATIN1,LATIN1 对所有字符都是单字节流处理,遇到不能处理的字节流,保持原样,那么在以上两种存入和检索的过程中都能保证数据一致,所以 MySQL 长期以来默认的编码都是 LATIN1。这种情形,看起来也没啥不对的点,数据也没乱码,那为什么还有选用其他的编码呢?原因就是对字符存储的字节数不一样,比如 emoji 字符 "❤",如果用 utf8mb4 存储,占用 3 个字节,那 varchar(12) 就能存放 12 个字符,但是换成 LATIN1,只能存 4 个字符。

总结

通过上面的详细说明,相信对 MySQL 乱码问题已经有一个很好的了解了。那来回顾下本篇的内容。本篇主要列列举了 MySQL 乱码可能出现的场景,并对应给出详细的处理方法以及相关建议,希望以后大家永远不会出现乱码问题。

使用MySQL导入数据时出现乱码的两种解决方法

使用MySQL导入数据时出现乱码的两种解决方法如下:1、添加 –default-character-set

先检查一下,目标数据编码。 56云 分享

使用目标库编码导入数据,如下:

2、修改数据库编码

此教程方法必须谨慎使用,需初始化数据库或将企业数据库技术可以覆盖情况下使用,否则导致数据库出现乱码