飞刀,又见飞刀

上一篇 / 下一篇  2008-04-11 10:41:39

呵呵,这个题目有点吓人的,借用了古龙的小说名字,

之所以想到这么个题目实在是需要探讨的是一个非常古老且常见且平凡发生且不易解决且令人难以解决的问题,说了这么多废话,很多人可能已经猜到了我想说什么了,对的,那就是从诞生计算机技术就诞生的字符集问题。

好了,再说废话要被人揍了,切入正题吧(注:PW同志曾经在一个两个小时的讲座里,在第一个小时零十分钟的时候说:下面我们切入正题

 

提到ORACLE的字符集的转换,很多人立刻会想到服务器端字符集和客户端字符集的转换,这点很多人都清楚,就不多说了,我今天主要想介绍一下OS字符集以及OS字符集在字符集转换中起的作用。

下面看一个DEMO:

环境:
OS:WINXP SP2
中文版
ORACLE 10.2.0.1
服务器和客户端在一台机器上
服务器字符集:AL32UTF8国家字符集AL16UTF16
客户端字符集: AL32UTF8

以下是在SQLPLUS里面的操作:

SQL> create table test (a varchar2(10));
琛ㄥ凡鍒涘缓銆?
SQL> insert into test values ('
');
宸插垱寤?1琛屻??
SQL> commit;
鎻愪氦瀹屾垚銆?
SQL> select a,dump(a)  from test;
A                                                                              
----------                                                                     
DUMP(A)                                                                        
--------------------------------------------------------------------------------

                                                                              
Typ=96 Len=2: 206,210               
                  

                                                                                
可以看到,服务器端和客户端都是UTF8但是显示出来的提示全部是乱码,

在看一下汉字""字的编码,我查了一下编码表,ZHS16GBK里面是206 98   ,UTF8里面是230 136 145,UTF16里面应该是98 17

但是实际的值是什么呢?实际的编码值是206 210,既不是GBK,也不是UTF8UTF16的编码,我查了一下其它的编码表,最终发现

206 210GB2312“我”字的编码

 

接着我把数据库客户端编码切换成ZHS16GBK,看看会发生什么

SQL> insert into test values('');

已创建1行。

SQL> commit;

提交完成。

SQL> select a,dump(a)  from test;

A                                                                              
--------------------                                                            
DUMP(A)                                                                        
--------------------------------------------------------------------------------

                                                                              
Typ=96 Len=3: 230,136,145

可以发现,数据库在插入时,准确的把""字转换成UTF8的编码,而在显示的时候又转换成了准确的汉字"",

怎么解释上面这个现象呢

 

事实上,通过试验我们可以发现OS的字符集实际是GB2312的,但是由于客户端字符集和服务器端字符集一致,所以在上传数据的时候,认为不存在字符集转换,所以就直接把OS的汉字编码上传上去了,这也是我们看到的库中实际存放的是GB2312“我”字编码206 210的原因,显示的时候同样的方式,认为数据库服务器与客户端字符集编码一致,不存在字符集转换,于是把206 210发到客户端,到了客户端,就正好原封不动的把206 210显示成为了汉字“我”。这也是造成提示乱码的原因,让GBK的窗口去解析UTF8的编码,从而产生乱码。

 

当客户端字符集是GBK的时候,执行INSERT的时候,ORACLE意识到服务器与客户端字符集不一致,产生一次字符集转换,把“我”字转换成UTF8编码230,136,145存入数据库中,select的时候做反操作,将UTF8转换成GBK编码显示出来。

 

 

下面顺带介绍一下一个经典的乱码问题,“靠”问题,

可能有人见过,就是在一个中文系统中所有的汉字全部显示为“靠”

下面介绍这种问题产生的原因:

服务器端:ZHS16GBK

客户端:WE8ISO8859P1

OS:GBK

假设库里存在汉字“我是从辉”,客户端做了一个select,ORACLE判断服务器客户端字符集不一致,于是做字符集转换,但是西欧字符集里面是没有汉字的,于是他会转换成特殊编码,一个倒问号,编码为”BF”,这样客户端得到的值就是“BF BF BF BF,OSGBK的,它会认为这是两个汉字,“BFBF,”BFBF”,恰巧是汉字“靠”的编码,于是你就会看到最终显示结果“靠靠”!


TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-07-20  
  12345
6789101112
13141516171819
20212223242526
2728293031  

数据统计

  • 访问量: 192
  • 日志数: 1024
  • 建立时间: 2008-02-02
  • 更新时间: 2008-04-11

RSS订阅

Open Toolbar