[20130106]關於不同字符集下clob欄位的儲存問題.txt

lfree發表於2013-01-06
[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<=1;

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個字
符就會發生這種情況。

許多問題留下以後研究。





來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/267265/viewspace-752202/,如需轉載,請註明出處,否則將追究法律責任。

相關文章