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

oracle中批量导出clob(大字段)内容至可读文本

原创 cqiwen 2024-12-26
251

说明:
  将oracle下含有大字段(clob)列的大量表数据导出到本地可读文件(如txt或csv)。

处理过程:
  先尝试在客户端(如dbeaver等)程序中进行查询,再复制粘贴结果集至excel或txt文本中。由于需要导出的表有200多个,且clob中的内容是html格式,单行clob列记录的内容可能达到几千上万个字符,再加上每张表有大约几十万条这样的数据,导致查询消耗很长时间,而在加载全部数据准备进行复制时,由于本地缓存空间不足,客户端直接hung住。
  之后又考虑对单个表先查询出结果再粘贴,这样结果集会小很多,但需要进行上百次这样的重复操作,工作量很大。
  再然后又想到用以前提到的方法,使用oracle的utl_file包来处理,详见《oracle导出大批量数据为csv或txt文件》,由于utl_file包只能支持varchar类型,也就是当字段中超过4000字符就直接报错了。但我们可以通过分段截取的方式进行处理来规避这个问题。

之后发现在某些客户端程序中有专门的数据导出至本地文本的功能,处理速度还是比较可观的。但由于这个客户端软件不是免费开源的,无法成为通用解决方案。

最后通过研究和实验,我找到一个比较方便的方法,该方法只适用于12C之后的版本:使用DBMS_LOB包中的DBMS_LOB.CLOB2FILE函数来处理。具体流程如下:

处理流程:
1)在DB服务器上创建目录:
mkdir /opt/temp

2)在DB服务器数据库中创建directory:
sqlplus / as sysdba
create directory temp as ‘/opt/temp’;
grant read,write on directory temp to cqiwen;

3)使用cqiwen用户登录,执行以下sql代码:

declare buf CLOB; tmptxt CLOB := ''; begin DBMS_LOB.CREATETEMPORARY(tmptxt, true); DBMS_LOB.OPEN(tmptxt, DBMS_LOB.LOB_READWRITE); for i in 1 .. 10 loop buf := 'hello,中国万岁!12345678'||CHR(13); DBMS_LOB.append(tmptxt, buf); end loop; DBMS_LOB.CLOSE(tmptxt); DBMS_LOB.CLOB2FILE(cl => tmptxt, flocation => 'TEMP', fname => 'test_get_clob.txt', openmode => 'wb'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); RAISE; end; /
复制

4)将 /opt/temp 下生成的test_get_clob.txt文件拷贝到本地,用文本工具即可打开查看。

业务实现:
修改上面的代码块,创建游标,游标中储存对多张表进行union all的查询结果集,然后依次取出游标中的每行记录,用游标循环替换掉上面代码块中的for循环,使用相同的方法进行写入即可。
以下是伪代码:

declare buf CLOB; tmptxt CLOB := ''; cursor cur1 as select id,content from tab1 union all select id,content from tab2 union all select id,content from tab3 union all ......; v_c cur1%rowtype; begin DBMS_LOB.CREATETEMPORARY(tmptxt, true); DBMS_LOB.OPEN(tmptxt, DBMS_LOB.LOB_READWRITE); open cur1; loop fetch cur1 into v_c; exit when cur1%notfound; buf := v_c.id||','||v_c.content||CHR(13); DBMS_LOB.append(tmptxt, buf); end loop; close cur1; DBMS_LOB.CLOSE(tmptxt); DBMS_LOB.CLOB2FILE(cl => tmptxt, flocation => 'TEMP', fname => 'test_get_clob.txt', openmode => 'wb'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); RAISE; end; /
复制
最后修改时间:2025-01-09 20:29:28
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论