Oracle数据导出新选择

我们经常会碰到数据导出的需求,例如将数据库中的数据导出成txt或者csv。从Oracle导出数据,其实有很多方法,例如通过PLSQL Developer图形化操作,但如果数据量大,就很可能卡;exp/expdp,两种工具算是比较常用的;还可以通过sqlldr,这是Oracle提供的工具,之前我们很多的备份脚本,就是通过sqlldr实现的,还是比较方便的;如果数据量少,甚至能通过spool,执行SQL,直接生成文件。

除此之外,Oracle还提供了UTL_FILE包,可以作为导出数据的手段,UTL_FILE包提供了读写操作系统文件的程序,可以参考,

https://docs.oracle.com/cd/E11882_01/appdev.112/e40758/u_file.htm#ARPLS069

我们通过一个实验来看下他的操作,目标是尝试导出这张测试表t_data的数据,一共200万,

SQL> select count(*) from t_data;
  COUNT(*)
----------
   2000000

首先要给执行导出的用户,授予UTL_FILE执行权限,

grant execute on utl_file to bisal;

创建一个目录,授权给该用户,

SQL> create directory utl_file_dir as '/home/oracle';
SQL> grant read, write on directory utl_file_dir to bisal;

执行如下的PL/SQL,他执行了select * from t_data,通过循环,将owner、object_name和object_type几个字段,以逗号","作为分隔符通过UTL_FILE写入目录UTL_FILE_DIR下的test.txt文件中,

declare
  VSFILE UTL_FILE.FILE_TYPE;   --定义用于接收文件句柄的类型
  V_CNT NUMBER;                --统计每个文件加载的行数,或者作为序号
begin
  VSFILE := UTL_FILE.FOPEN('UTL_FILE_DIR', 'test.txt', 'w');
  V_CNT := 1;
  for x in (select * from t_data)
    loop
      UTL_FILE.PUT_LINE(VSFILE, V_CNT || ',' || x.owner || ',' || x.object_name || ',' || x.object_type);
      V_CNT := V_CNT + 1;
    end loop;
    DBMS_OUTPUT.PUT_LINE('Finished. All Load Rows: ' || V_CNT);
    UTL_FILE.FFLUSH(VSFILE);
    UTL_FILE.FCLOSE(VSFILE);
    EXCEPTION WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE(SUBSTR(SQLERRM, 1, 2000));
end;
/

200万数据导出,大约用时16秒,可以看到test.txt的内容,一共200万,

[oracle@bisal ~]$ tail test.txt
1999991,BD_ADMIN,DSK_FUNC_PARAM,SYNONYM
1999992,BD_ADMIN,DSK_FUNC_IDX_PARAM,SYNONYM
1999993,BD_ADMIN,DSK_FUNC_FIN_TYP,SYNONYM
1999994,BD_ADMIN,DSK_FUNC_FIN,SYNONYM
1999995,BD_ADMIN,DSK_DB_CFG,SYNONYM
1999996,BD_ADMIN,DSK_DATA_SOUR_SUP,SYNONYM
1999997,BD_ADMIN,DSK_DATA_SOUR_DEF,SYNONYM
1999998,BD_ADMIN,DSK_DATA_SOUR,SYNONYM
1999999,SYS,WRH$_DB_CACHE_ADVICE,TABLE PARTITION
2000000,SYS,WRH$_DB_CACHE_ADVICE_PK,INDEX PARTITION

同时这个UTL_FILE还支持文件的拆分操作,如下所示,从test.txt读出1024000行,写入test_01.txt,用时3秒,

BEGIN
  UTL_FILE.FCOPY('UTL_FILE_DIR', 'test.txt', 'UTL_FILE_DIR', 'test_01.txt', 1, 1024000);
END;
/

可以看到,test_01.txt存储了1024000行,

[oracle@jf-vra-app1461 ~]$ tail test_01.txt
1023991,PUBLIC,/a522e2b5_AMD64AbstractMIR2LIR,SYNONYM
1023992,SYS,/637da884_AMD64AbstractMIR2LIR,JAVA CLASS
1023993,PUBLIC,/637da884_AMD64AbstractMIR2LIR,SYNONYM
1023994,SYS,/8b220592_AMD64AbstractMIR2LIR,JAVA CLASS
1023995,PUBLIC,/e0f792c5_IA64BundleState2,SYNONYM
1023996,SYS,/84ed886b_IA64BundleState3,JAVA CLASS
1023997,PUBLIC,/84ed886b_IA64BundleState3,SYNONYM
1023998,SYS,/64cbb84a_IA64BundleStateState,JAVA CLASS
1023999,PUBLIC,/64cbb84a_IA64BundleStateState,SYNONYM
1024000,SYS,/b1421140_RegFileInfoTemplate,JAVA CLASS

将test.txt的1024001行到200万行,写入test_02.txt,

BEGIN
  UTL_FILE.FCOPY('UTL_FILE_DIR', 'test.txt', 'UTL_FILE_DIR', 'test_02.txt', 1024001, null);
END;
/

可以看到,test_02.txt,存储到了200万行,

[oracle@jf-vra-app1461 ~]$ tail test_02.txt
1999991,BD_ADMIN,DSK_FUNC_PARAM,SYNONYM
1999992,BD_ADMIN,DSK_FUNC_IDX_PARAM,SYNONYM
1999993,BD_ADMIN,DSK_FUNC_FIN_TYP,SYNONYM
1999994,BD_ADMIN,DSK_FUNC_FIN,SYNONYM
1999995,BD_ADMIN,DSK_DB_CFG,SYNONYM
1999996,BD_ADMIN,DSK_DATA_SOUR_SUP,SYNONYM
1999997,BD_ADMIN,DSK_DATA_SOUR_DEF,SYNONYM
1999998,BD_ADMIN,DSK_DATA_SOUR,SYNONYM
1999999,SYS,WRH$_DB_CACHE_ADVICE,TABLE PARTITION
2000000,SYS,WRH$_DB_CACHE_ADVICE_PK,INDEX PARTITION

如果内容不含中文字,可以直接将txt后缀改成csv,就可以使用excel打开,如下所示,

903cbcb073dc9d88143a1877b472a336.png

如果含中文,UTL_FILE包生成的文件是unix-dos格式,不能正确识别中文字,因此不能直接将这个txt文件后缀改成csv格式的,此时,可以在文本编辑工具中打开txt文件,复制粘贴到新的文件中,通过另存为csv格式,达到生成excel的目的。

参考资料,

https://www.modb.pro/db/218644

近期更新的文章:

什么是“信息化”和“数字化”?

线上的数据技术嘉年华体验分享

推荐个免费的MySQL培训资源

2021第十一届数据技术嘉年华

青春的记忆,小个子前锋,阿圭罗

文章分类和索引:

公众号900篇文章分类和索引

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值