暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

如何解决Oracle DUL恢复clob时中文乱码问题?

原创 Roger 2014-09-14
740
闲来无聊,研究了一下Oracle DUL 恢复clob的情况,对于中文存储。这一点DUL赶ODU差距一大截。用起来也很不顺手。

不过这当是无聊玩玩了,下面来说准备测试环境,本文仅供参考,不过各种Oracle数据恢复可以联系我!
++++准备测试表

[ora10g@killdb ~]$ sqlplus roger/roger

SQL*Plus: Release 10.2.0.5.0 - Production on Sun Sep 14 03:58:10 2014

Copyright (c) 1982, 2010, Oracle. All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

www.killdb.com>select * from test_clob;

ID NAME
---------- -------------------------------------------
1 我爱中国
2 我帅爆了
3 killdb.com

www.killdb.com>desc test_clob
Name Null? Type
---------------------------------------- -------- ---------------------------
ID NUMBER
NAME CLOB

www.killdb.com>

DUL> desc roger.test_clob;
Table ROGER.TEST_CLOB
obj#= 58448, dataobj#= 58448, ts#= 6, file#= 5, block#=835
tab#= 0, segcols= 2, clucols= 0
Column information:
icol# 01 segcol# 01 ID len 22 type 2 NUMBER(0,-127)
icol# 02 segcol# 02 NAME len 4000 type 112 CLOB cs 852(ZHS16GBK)
LOB Segment: dataobj#= 58449, ts#= 6, file#= 5, block#=843 chunk=1
LOB Index: dataobj#= 58450, ts#= 6, file#= 5, block#=851
DUL>
复制



将该block的数据dump,我们来看下数据实际上在block内是怎么存放的,如下:

tab 0, row 0, @0x1ee4
tl: 51 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 02
col 1: [44]
00 54 00 01 02 0c 80 00 00 02 00 00 00 01 00 00 00 26 a3 cd 00 18 09 00 00
00 00 00 00 08 00 00 00 00 00 01 62 11 72 31 4e 2d 56 fd
tab 0, row 1, @0x1eab
tl: 57 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 03
col 1: [50]
00 54 00 01 02 0c 80 00 00 02 00 00 00 01 00 00 00 26 a3 ce 00 1e 09 00 00
00 00 00 00 0e 00 00 00 00 00 01 00 62 00 11 00 5e 00 05 00 72 00 06 00 4e
tab 0, row 2, @0x1e58
tl: 83 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 04
col 1: [76]
00 54 00 01 02 0c 80 00 00 02 00 00 00 01 00 00 00 26 a3 cf 00 38 09 00 00
00 00 00 00 28 00 00 00 00 00 01 00 00 00 6b 00 00 00 69 00 00 00 6c 00 00
00 6c 00 00 00 64 00 00 00 62 00 00 00 2e 00 00 00 63 00 00 00 6f 00 00 00
6d
end_of_block_dump
复制

这里我们以第一行的数据为例,我们知道,我第一行的数据其实只要4个汉字,为什么dump的col 1这么长呢?

前面的84个byte其实的lob header的信息,后面的8个bytes才是实际的lob data。可以看到这不是我们以往

说知道的16进制,而是unicode编码。如果你去对照unicode的中文编码表,这8个byte正好表示我们的4个汉字。

首先我们来测试dul,正常情况下,你会发现dul抽取的信息直接sqlldr加载之后,中文都是乱码。

####不经过转码的情况

--unload table数据
DUL> unload table roger.test_clob;
. unloading (index organized) table LOB01400353
DUL: Warning: Recreating file "LOB01400353.ctl"
0 rows unloaded
Preparing lob metadata from lob index
Reading LOB01400353.dat 0 entries loaded and sorted 0 entries
. unloading table TEST_CLOB
DUL: Warning: Recreating file "ROGER_TEST_CLOB.ctl"
3 rows unloaded
DUL>

--创建相同表结构的测试表
www.killdb.com>create table test_clob_1 as select * from test_clob where 1=0;

Table created.

www.killdb.com>

--修改ctl文件
修改ROGER_TEST_CLOB.ctl中的表名称,将内容修改为如下:
load data
CHARACTERSET ZHS16GBK
infile 'ROGER_TEST_CLOB.dat'
insert
into table "ROGER"."TEST_CLOB_1"
fields terminated by whitespace
(
"ID" CHAR(1) enclosed by X'7C'
,"NAME" LOBFILE(LF58449) TERMINATED BY EOF NULLIF LF58449 = 'NONE', LF58449 FILLER CHAR(20) enclosed by X'7C'
)
说明:其实就是替换了一下表名称.

--将数据加载到test_clob_1
[ora10g@killdb dul]$ sqlldr roger/roger control=ROGER_TEST_CLOB.ctl

SQL*Loader: Release 10.2.0.5.0 - Production on Sun Sep 14 04:11:03 2014

Copyright (c) 1982, 2007, Oracle. All rights reserved.

Commit point reached - logical record count 3
[ora10g@killdb dul]$

--验证test_clob_1 的数据
www.killdb.com>show user
USER is "ROGER"
www.killdb.com>select * from test_clob_1;

ID NAME
---------- ---------------------------------------------------------
1 br1N-V
2 b^rN
3

www.killdb.com>
复制


我们可以看到,几乎全是乱码。

开始我将unload产生的lob文件用UE打开,以及对比发现是以unicode的方式存在的,因此我们需要转码才行。


#### 经过转码的测试
使用Linux自带的iconv工具进行转码,该工具非常强大,支持多种编码,如下:


[ora10g@killdb dul]$ iconv -l|grep GB
CN-GB//
CSGB2312//
CSISO58GB1988//
EBCDIC-CP-GB//
GB//
GB2312//
GB13000//
GB18030//
GBK//
GB_1988-80//
GB_198880//
ISO646-GB//
[ora10g@killdb dul]$ iconv -l|grep UCS
10646-1:1993/UCS4/
CSUCS4//
ISO-10646/UCS2/
ISO-10646/UCS4/
UCS-2//
UCS-2BE//
UCS-2LE//
UCS-4//
UCS-4BE//
UCS-4LE//
UCS2//
UCS4//

[ora10g@killdb dul]$ mv LF0002.lob LF0002.lob.old
[ora10g@killdb dul]$ iconv -f UCS-2BE -t gb2312 LF0002.lob.old > LF0002.lob
复制

加载数据之前,先将表truncate清空:

www.killdb.com>truncate table test_clob_1;

Table truncated.

++++加载数据
[ora10g@killdb dul]$ sqlldr roger/roger control=ROGER_TEST_CLOB.ctl

SQL*Loader: Release 10.2.0.5.0 - Production on Sun Sep 14 04:27:43 2014

Copyright (c) 1982, 2007, Oracle. All rights reserved.

Commit point reached - logical record count 3
[ora10g@killdb dul]$

++++ 验证test_clob_1数据

www.killdb.com>select * from test_clob_1;

ID NAME
---------- --------------------------------------------------------
1 br1N-V
2 我帅爆了
3

www.killdb.com>
复制

我们可以看到,经过处理的第2条数据正常的显示了。


可见,结合iconv工具,Oracle DUL可以完美的支持clob的中文恢复。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论