Linux安全网 - Linux操作系统_Linux 命令_Linux教程_Linux黑客

会员投稿 投稿指南 本期推荐:
搜索:
您的位置: Linux安全网 > Linux编程 > 数据库管理 > » 正文

mysql 乱码产生探讨

来源: dubiousway 分享至:

mysql 乱码产生探讨

实验一 
1。首先,在下面情况下: 
mysql> show variables like 'character_set_%'; 
+--------------------------+---------------------------------------+
| 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       | D:\Programs\mysql5045\share\charsets\ |
+--------------------------+---------------------------------------+ 
建表,并加入3个记录:大,阿,爱 
 
2。set character_set_results=utf8; 
则显示:(cmd窗口中,cmd窗口代码页936) 

大->麓贸 
阿->掳垄 
爱->掳庐 
 
分析编码: 
 
大U:5927,GBK:B4F3
麓U:9E93,GBK:C2B4
贸U:8D38,GBK:C3B3


阿U:963F,GBK:B0A2
掳U:63B3,GBK:C2B0
垄U:5784,GBK:C2A2

爱U:7231,GBK:B0AE
掳U:63B3,GBK:C2B0
庐U:5E90,GBK:C2AE 
 
3。改成
set character_set_results=gb2312; 
一样是乱码 
 
4。结论: 
  • 乱码的产生,是由于单字节向多字节扩展引起的。B0A2 如果作为单字节存储(虽然表示的是1个汉字,但是因为是latin1单字节,所以认为B0A2是不相关的两个字符),此时如果把character_set_results变成utf8多字节,那么数据库mysql 会试图把每个单字节扩展成近似的(不知道具体的算法)双字节。所以乱码 
  • 反之,多字节向单字节转换时,不会有变动,仅仅是原来2各字节表示的一个字符‘B0A2’变成了表示两个字符而已。---- 这个说法经验证是错误的。 
  • 数据库存储的内容(磁盘上,内存里)不会受character_set_的影响,只是提交,查询的过程中,受到字符集转换的影响。
 

实验二 
1。 
create table y (id int, name char(4)) default charset gb2312; 
 
2。在不改变默认character_set_ 是 latin1的情况下,如果插入一个汉字,则显示乱码 
 
3。改成 set names gb2312,显示没问题(cmd窗口中,cmd窗口代码页936) 
 
4。我原以为如上述实验1种的结论2,“多字节向单字节转换时,不会有变动”。所以我开始以为,set names gb2312 后,把 character_set_results 改成latin1,显示不会出问题。结果, 
一个汉字,则显示一个问号;两个汉字,则显示两个问号的乱码(估计一个问号代表一个字符)。也就是说,改成character_set_results = latin1后,多字节的数据存储,在向单字节表示转换时,mysql把提出的信息“缩水了”,把两个字节,换算成了一个字节。 
 
5。如何,不让mysql缩水呢,我想到了character_set_results = binary;结果,果然显示正常。 
 
PS 
  • 开发的使用mysql的应用程序,是对应作为独立的使用自己的character_set_client的字符集的
  • cmd 窗口登陆mysql,也是作为一个独立的,拥有自己character_set_client变量的应用
  • 同理,打开不同的cmd窗口,都拥有独自的character_set_client变量
 

实验三 07/16/2010 
 
1。建一个默认字符集utf8的表(用navicat ,在utf8的界面下 代码页65001),并且插入utf8编码的汉字‘大学’ 
2。切换到mysql console(代码页936) 
3。set names gbk; 然后显示刚才所建立的表,能正确现实吗? ---- 能!当然,只把character_set_results 成 gbk,也能正常显示 
 

实验四 
 
1。mysql console(代码页936)建立一个表x3 ( name char(32) ),默认字符集 default charset gbk; 
2。默认环境变量   
| 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_set_client   character_set_connection character_set_results 是latin1的情况下,插入数据:insert x3 values('大'); 
显示:ERROR 1406 (22001): Data too long for column 'name' at row 1 
3。set character_set_client=gbk;然后 insert x3 values('大');插入没有问题,但显然,数据经过 (character_set_connection=latin1)的转换,已经是有损了 
4。不管 character_set_results 设不设成 gbk,都不能正常显示结果 
5。set names gbk;则插入现实都没问题。并且此时,一个uf8字符集的表的显示也没问题(实验三)。而且进行连接查询,亦没问题。 
6。当然,set names utf8,如果在一个utf8的软件界面上,显示输出也没问题(navicat 验证了) 
7。如果设成 set names binary。在936代码页的显示界面上,可以看到,x3依然可以正常现实;但像实验三那样建的表就不能正常显示了。 
-------- 
分析第2点:Data too long for column 'name' at row 1 
  1. 我的char 够长,插入数据够短,所以不是数据太长了。也就是说这个提示是错误的。
  2. 我知道,如果表x3 默认字符集 是latin1的话,插入是没问题的(一直以来都是这么玩的);这是因为,虽然输入端mysql console 代码页是936,但因为三个主环境变量character_set_c%都是latin1,所以,mysql 认为insert x3 values('大') 输入的是2个字符(当然,如果从utf8界面输入,可能就认为是输入3个字符)。存储的自然也是2个字符。显示的时候也是显示的2个字符,只不过936代码页把这两个字符自然组合,显示成汉字了(早期dos环境常见现象)。
  3. 当默认字符集变为gbk的时候,发生了什么?不知道。。。。。 
 

实验五 
一个很狗屎的问题出现了:936 mysql console 
环境变量如 实验一.1。 
 
mysql> set names latin1;
Query OK, 0 rows affected (0.00 sec)

mysql> create table x4 (
    -> name char(32) primary key);
Query OK, 0 rows affected (0.09 sec)

mysql> drop table x4;
Query OK, 0 rows affected (0.06 sec)

mysql> create table x4 (
    -> name char(32) primary key) default charset utf8;
Query OK, 0 rows affected (0.10 sec)

mysql> insert x4 values('乃');
Query OK, 1 row affected (0.04 sec)

mysql> create table x5 (
    -> name char(32) primary key) default charset gbk;
Query OK, 0 rows affected (0.09 sec)

mysql> insert x5 values('乃');
ERROR 1406 (22001): Data too long for column 'name' at row 1
mysql>
 
 
结论,我实在对实验四中分析的第3点做出结论。character_set_system utf8 有关 ~~ 


Tags:
分享至:
最新图文资讯
1 2 3 4 5 6
验证码:点击我更换图片 理智评论文明上网,拒绝恶意谩骂 用户名:
关于我们 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 发展历史