[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个字
符就会发生这种情况。
许多问题留下以后研究。