Mysql中文查询没有结果,插入中文变成?的解决



【问题描述】所在项目使用mysql数据库,原先只有测试库和生产库。因权限管理方便的原因,新增开发库但使用的时候出现编码问题。

系统中的所有的中文查询,没有结果。插入中文数据也都变成问号。将SQL考出来用Toad for Mysql 执行,也是所有的中文查询,没有结果。插入中文数据也都变成问号。于是开始了以下的研究。


【MYSQL数据库字符集】

字符集(Character set)和排序方式(Collation)。

MySQL对于字符集的支持细化到四个层次: 服务器(server),数据库(database),数据表(table)和连接(connection)。

MySQL对于字符集的指定可以细化到一个数据库,一张表,一列,应该用什么字符集。

【查看字符集设置与查看排序方式】

show variables like 'character_set_%';

show variables like 'collation_%';

结果:

Variable_name | Value | 
+--------------------------+----------------------------+ 
| character_set_client | latin1 | 
| character_set_connection | latin1 | 
| character_set_database | latin1 | 
| character_set_filesystem | binary | 
| character_set_results | latin1 | 
| character_set_server | latin1 | 
| character_set_system | utf8 | 
| character_sets_dir | /usr/share/mysql/charsets/ | 

【关于字符集设置与排序方式】

Character set顾名思义,就是字符、以及字符对应的编码的集合。例如简体中文字符集gb2312就包括简体中文中的所有规定汉字,以及每个汉字对应的代码。

Collation,是指比较字符的规则的集合。有了比较规则,才能够将一组数据排序——例如按照英文字母顺序排序、汉字按照拼音顺序排序等等。显然,针对同样一组字符集可以有不同的排序标准、规则。例如汉字可以按照拼音排序,也可以按照笔画多少排序。尤其是Unicode的字符集,由于其可以包含不同种类的语言,所以可以按照各种语言的排序方法排序。此外,完全按照字符在字符集里的编码进行比较的方式称为binary比较。

【mysql】

在MySQL的体系中有三处字符集和collation:服务器(数据),连接,客户端。乍一看体系清楚明了,其实并不是这样。下面就一一介绍。

[1] 服务器(数据)端的字符集和collation,可以分成四级逐层指定——server, database, table, column。当MySQL存取位于某一列(column)的数据时,如果column的字符集和collation没有指定,就会向上追溯table的;如果table也没有指定字符集和collation,就以database的字符集和collation作为默认值;如果database仍旧没有指定,那么就以服务器的字符集和collation作为默认值。

那么server的字符集和collation的默认值又是从哪里来的呢?答案是,配置文件(my.ini)和mysqld(或者mysqld-nt)的命令行参数中都可以指定。如果不幸的,你根本没有在my.ini或者命令行中指定,那么MySQL就会使用编译MySQL时指定的默认字符集——latin1。

但是,需要注意的是,如果安装MySQL时选择了多语言支持(一般用中文的都会选择吧),安装程序会自动在配置文件中设置default-character-set=utf8

这样,所有创建的数据库、表,除非明确指出使用其它字符集,都会默认的使用utf作为数据的字符集(同时使用utf8_general_ci作为默认collation,因为它是utf8的默认collation)。

character_set_server :服务器的字符集
collation_server :服务器的collation
character_set_database :数据库字符集
collation_database :数据库的collation

[2] 客户端。对于客户端传送来的literal string(例如INSERT,UPDATE语句当中的值),MySQL需要知道它们是什么编码。同时,MySQL返回给客户端的值(例如SELECT语句的返回值),也可以按照指定的编码返回。

character_set_client:客户端发送过来文字的字符集
character_set_results:发送给客户端的结果所使用的字符集

[3] 连接。用于连接的字符集和collation,是指MySQL在接受到客户端发送来的文本之后,转换成何种字符集,用什么规则进行比较。需要注意的是,如果是将文本和数据库中某个column的值比较,将优先使用该column的字符集和collation。

character_set_connection:用于连接的字符集
collation_connection:用于连接的collation

【问题分析】

先执行语句

show variables like 'character_set_%';

show variables like 'collation_%';

客户端(页面)采用的是UTF-8编码,由于传递给MySQL的文本都是用UTF-8编码的,但是由于上述系统变量设置不当,这些UTF-8编码的文本被MySQL当作是latin1编码的,并且由于数据库本身是utf8,因此把这些“latin1文本”又转换成了utf8。这样,一个汉字居然需要6bytes(一个汉字作为UTF-8是3bytes,被当作latin1进行了转换,每个latin1字符转换成2bytes的UTF-8编码)。这就不难理解为什么数据库存储的是“乱码”了。

因此需要改的参数确定是:

character_set_client,character_set_connection,character_set_server,character_set_results改成utf8

排序方式:

collation_connection,collation_server改成utf8_general_ci

【注意】如果安装MySQL时选择了多语言支持(一般用中文的都会选择吧),安装程序会自动在配置文件中设置default-character-set=utf8

这样,所有创建的数据库、表,除非明确指出使用其它字符集,都会默认的使用utf作为数据的字符集(同时使用utf8_general_ci作为默认collation,因为它是utf8的默认collation)。

【修改语句】

  SET character_set_client = utf8;
  SET character_set_results = utf8;
  SET character_set_connection = utf8; 

    SET character_set_server= utf8;

     SET collation_connection=utf8_general_ci;

    SET collation_server=utf8_general_ci;

【执行结果】

   以上分析的参数 都改成utf8了,但是还是没有解决问题。重启mysql数据库试试看

   还是没解决,后续在找下思路

   【后续】

linux下修改/etc/my.cnf,在[mysqld]下加入default-character-set = utf8,[client]下加入default-character-set = utf8,([mysqld]与[mysql]的区别是:mysqld是用来启动mysql数据库的命令 ,mysql是打开并执行sql语句的命令),service mysql restart重启mysql服务器。

再看,问题解决了。

【分析】mysql 中my.cnf是mysql配置文件。如果没有在[client]和[mysqld]中配置默认字符utg8,那么在mysql启动的时候会按照默认字符集latin1启动。引起mysql不认识utf8数据。只是用set修改参数并不能解决问题,你一重启,又变回latin1了。但是不重启又不会生效。所以最终的解决,还是修改了my.cnf文件


END


【问题描述】所在项目使用mysql数据库,原先只有测试库和生产库。因权限管理方便的原因,新增开发库但使用的时候出现编码问题。

系统中的所有的中文查询,没有结果。插入中文数据也都变成问号。将SQL考出来用Toad for Mysql 执行,也是所有的中文查询,没有结果。插入中文数据也都变成问号。于是开始了以下的研究。


【MYSQL数据库字符集】

字符集(Character set)和排序方式(Collation)。

MySQL对于字符集的支持细化到四个层次: 服务器(server),数据库(database),数据表(table)和连接(connection)。

MySQL对于字符集的指定可以细化到一个数据库,一张表,一列,应该用什么字符集。

【查看字符集设置与查看排序方式】

show variables like 'character_set_%';

show variables like 'collation_%';

结果:

Variable_name | Value | 
+--------------------------+----------------------------+ 
| character_set_client | latin1 | 
| character_set_connection | latin1 | 
| character_set_database | latin1 | 
| character_set_filesystem | binary | 
| character_set_results | latin1 | 
| character_set_server | latin1 | 
| character_set_system | utf8 | 
| character_sets_dir | /usr/share/mysql/charsets/ | 

【关于字符集设置与排序方式】

Character set顾名思义,就是字符、以及字符对应的编码的集合。例如简体中文字符集gb2312就包括简体中文中的所有规定汉字,以及每个汉字对应的代码。

Collation,是指比较字符的规则的集合。有了比较规则,才能够将一组数据排序——例如按照英文字母顺序排序、汉字按照拼音顺序排序等等。显然,针对同样一组字符集可以有不同的排序标准、规则。例如汉字可以按照拼音排序,也可以按照笔画多少排序。尤其是Unicode的字符集,由于其可以包含不同种类的语言,所以可以按照各种语言的排序方法排序。此外,完全按照字符在字符集里的编码进行比较的方式称为binary比较。

【mysql】

在MySQL的体系中有三处字符集和collation:服务器(数据),连接,客户端。乍一看体系清楚明了,其实并不是这样。下面就一一介绍。

[1] 服务器(数据)端的字符集和collation,可以分成四级逐层指定——server, database, table, column。当MySQL存取位于某一列(column)的数据时,如果column的字符集和collation没有指定,就会向上追溯table的;如果table也没有指定字符集和collation,就以database的字符集和collation作为默认值;如果database仍旧没有指定,那么就以服务器的字符集和collation作为默认值。

那么server的字符集和collation的默认值又是从哪里来的呢?答案是,配置文件(my.ini)和mysqld(或者mysqld-nt)的命令行参数中都可以指定。如果不幸的,你根本没有在my.ini或者命令行中指定,那么MySQL就会使用编译MySQL时指定的默认字符集——latin1。

但是,需要注意的是,如果安装MySQL时选择了多语言支持(一般用中文的都会选择吧),安装程序会自动在配置文件中设置default-character-set=utf8

这样,所有创建的数据库、表,除非明确指出使用其它字符集,都会默认的使用utf作为数据的字符集(同时使用utf8_general_ci作为默认collation,因为它是utf8的默认collation)。

character_set_server :服务器的字符集
collation_server :服务器的collation
character_set_database :数据库字符集
collation_database :数据库的collation

[2] 客户端。对于客户端传送来的literal string(例如INSERT,UPDATE语句当中的值),MySQL需要知道它们是什么编码。同时,MySQL返回给客户端的值(例如SELECT语句的返回值),也可以按照指定的编码返回。

character_set_client:客户端发送过来文字的字符集
character_set_results:发送给客户端的结果所使用的字符集

[3] 连接。用于连接的字符集和collation,是指MySQL在接受到客户端发送来的文本之后,转换成何种字符集,用什么规则进行比较。需要注意的是,如果是将文本和数据库中某个column的值比较,将优先使用该column的字符集和collation。

character_set_connection:用于连接的字符集
collation_connection:用于连接的collation

【问题分析】

先执行语句

show variables like 'character_set_%';

show variables like 'collation_%';

客户端(页面)采用的是UTF-8编码,由于传递给MySQL的文本都是用UTF-8编码的,但是由于上述系统变量设置不当,这些UTF-8编码的文本被MySQL当作是latin1编码的,并且由于数据库本身是utf8,因此把这些“latin1文本”又转换成了utf8。这样,一个汉字居然需要6bytes(一个汉字作为UTF-8是3bytes,被当作latin1进行了转换,每个latin1字符转换成2bytes的UTF-8编码)。这就不难理解为什么数据库存储的是“乱码”了。

因此需要改的参数确定是:

character_set_client,character_set_connection,character_set_server,character_set_results改成utf8

排序方式:

collation_connection,collation_server改成utf8_general_ci

【注意】如果安装MySQL时选择了多语言支持(一般用中文的都会选择吧),安装程序会自动在配置文件中设置default-character-set=utf8

这样,所有创建的数据库、表,除非明确指出使用其它字符集,都会默认的使用utf作为数据的字符集(同时使用utf8_general_ci作为默认collation,因为它是utf8的默认collation)。

【修改语句】

  SET character_set_client = utf8;
  SET character_set_results = utf8;
  SET character_set_connection = utf8; 

    SET character_set_server= utf8;

     SET collation_connection=utf8_general_ci;

    SET collation_server=utf8_general_ci;

【执行结果】

   以上分析的参数 都改成utf8了,但是还是没有解决问题。重启mysql数据库试试看

   还是没解决,后续在找下思路

   【后续】

linux下修改/etc/my.cnf,在[mysqld]下加入default-character-set = utf8,[client]下加入default-character-set = utf8,([mysqld]与[mysql]的区别是:mysqld是用来启动mysql数据库的命令 ,mysql是打开并执行sql语句的命令),service mysql restart重启mysql服务器。

再看,问题解决了。

【分析】mysql 中my.cnf是mysql配置文件。如果没有在[client]和[mysqld]中配置默认字符utg8,那么在mysql启动的时候会按照默认字符集latin1启动。引起mysql不认识utf8数据。只是用set修改参数并不能解决问题,你一重启,又变回latin1了。但是不重启又不会生效。所以最终的解决,还是修改了my.cnf文件


END


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值