[20130106]关于不同字符集下clob字段的存储问题.txt

[20130106]关于不同字符集下clob字段的存储问题.txt

工作需要,需要把几个数据库合并在一起,由于以前数据库使用的字符集是AMERICAN_AMERICA.US7ASCII,而现在的数据库使用
SIMPLIFIED CHINESE_CHINA.ZHS16GBK,整合的时候需要修改字符集,统一到字符集SIMPLIFIED CHINESE_CHINA.ZHS16GBK。
具体看连接:
http://space.itpub.net/267265/viewspace-752174

但是出现一点小问题,就是转换后字符集出现乱码。自己做一些研究看看:

1.建立测试例子:

--在两个不同字符集的数据库上建立表(其中中文字符集11G,英文字符集为10g):

CREATE TABLE t  ( ID NUMBER,c1 VARCHAR2(20),c2 CLOB ) tablespace test;
insert into t values (1,'test123测试','test123测试');
commit;

2.先看中文字符集的情况:
SQL> select * from v$version where rownum

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

SQL> column c2 format a20
SQL> select rowid,t.*,dump(t.c1,16) x20 from t;

ROWID                      ID C1                   C2                   X20
------------------ ---------- -------------------- -------------------- ------------------------------------------------------------
AABBg9AAIAAAACPAAA          1 test123测试          test123测试          Typ=1 Len=11: 74,65,73,74,31,32,33,b2,e2,ca,d4
--注: 如果dump(t.c2,16) 会出现ORA-00932: inconsistent datatypes: expected - got CLOB.
--可以知道"测试" 对应的ascii码是 b2 e2 ca d4

SQL> @ lookup_rowid  AABBg9AAIAAAACPAAA

    OBJECT       FILE      BLOCK        ROW
---------- ---------- ---------- ----------
    268349          8        143          0

SQL> alter system checkpoint;
System altered.

BBED> set dba 8,143
        DBA             0x0200008f (33554575 8,143)

BBED> p    *kdbr
rowdata[0]
----------
ub1 rowdata[0]                              @8115     0x2c

BBED> x /rnxx
rowdata[0]                                  @8115
----------
flag@8115: 0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@8116: 0x01
cols@8117:    3

col    0[2] @8118: 1
col   1[11] @8121:  0x74  0x65  0x73  0x74  0x31  0x32  0x33  0xb2  0xe2  0xca  0xd4
col   2[54] @8133:  0x00  0x54  0x00  0x01  0x02  0x0c  0x80  0x00  0x00  0x02  0x00  0x00  0x00  0x01  0x00  0x00  0x01  0xd8  0x50  0xb3
                    0x00  0x22  0x09  0x00  0x00  0x00  0x00  0x00  0x00  0x12  0x00  0x00  0x00  0x00  0x00  0x01  0x00  0x74  0x00  0x65
                                                                                                                    ~~~~~~~~~~~~~~~~~~~~~~ 
                    0x00  0x73  0x00  0x74  0x00  0x31  0x00  0x32  0x00  0x33  0x6d  0x4b  0x8b  0xd5
                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--对比可以发现c2字段前面有一个头,从下划线开始才是对应的信息。英文字符t对应的0x00 0x74.而中文的"测"对应的是0x6d  0x4b。
--使用windows的记事本编辑文件,输入"test123测试",保存时选择的另存为编码是unicode。
--再使用一些查看二进制文本的工具查看文件,发现:
0000000: 7400 6500 7300 7400 3100 3200 3300 4b6d  t.e.s.t.1.2.3.Km
0000010: d58b 0d0a                                ....

--可以发现如果两个字符对调,完全符合结果,可以确定clob保存的就是unicode的格式。

3.再来看看英文字符集的情况:
--操作步骤同上。
SQL> column c2 format a20
SQL> column x20 format a60
SQL> select rowid,t.*,dump(t.c1,16) x20 from t;

ROWID                      ID C1                   C2                   X20
------------------ ---------- -------------------- -------------------- ------------------------------------------------------------
AABBs5AAfAAEbfIAAA          1 test123测试          test123测试          Typ=1 Len=11: 74,65,73,74,31,32,33,b2,e2,ca,d4

SQL> @ lookup_rowid  AABBs5AAfAAEbfIAAA

    OBJECT       FILE      BLOCK        ROW
---------- ---------- ---------- ----------
    269113         31    1161160          0

BBED> x /rnxx
rowdata[0]                                  @16314
----------
flag@16314:0x2c (KDRHFL, KDRHFF, KDRHFH)
lock@16315:0x01
cols@16316:   3

col    0[2] @16317: 1
col   1[11] @16320:  0x74  0x65  0x73  0x74  0x31  0x32  0x33  0xb2  0xe2  0xca  0xd4
col   2[47] @16332:  0x00  0x54  0x00  0x01  0x02  0x0c  0x00  0x00  0x00  0x01  0x00  0x00  0x00  0x01  0x00  0x00  0x02  0x29  0x85  0x91
                     0x00  0x1b  0x09  0x00  0x00  0x00  0x00  0x00  0x00  0x0b  0x00  0x00  0x00  0x00  0x00  0x01  0x74  0x65  0x73  0x74
                                                                                                                     ~~~~~~~~~~~~~~~~~~~~~~ 
                     0x31  0x32  0x33  0xb2  0xe2  0xca  0xd4
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--对比可以发现c2字段,下划线开始保存的信息与c1内容相同。

这样当转化字符集后出现乱码就不足为怪了。另外注意相同的内容在英文字符下仅仅占用47字节,而中文字符集下占用54字节。
换一句话讲如果你使用中文字符集,而clob保存的内容是英文字符的话占用空间将几乎是英文字符集的2倍。

另外当保存的内容长度大于3964的话,将不保存在当前块中,而是分配另外的chunk。而如果这些内容是英文的话将大于3964/2=1982个字
符就会发生这种情况。

许多问题留下以后研究。





上一篇:Spring事务配置的五种方式(转自robbie的博客)


下一篇:能够定制Intel CPU的国产展讯芯片 有机会悄然崛起?