SQL*Loader 是用于将外部数据进行批量高速加载的数据库的最高效工具,可用于将多种平面格式文件加载到Oracle数据库。SQL*Loader支持传统路径模式以及直接路径这两种加载模式。关于SQL*Loader的具体用法可以参考Oracle Utilities 手册或者SQL*Loader使用方法。那么如何以SQL*Loader能识别的方式高效的卸载数据呢? Tom大师为我们提供了一个近乎完美的解决方案,是基于exp/imp,Datapump方式迁移数据的有力补充。本文基于此给出描述,并通过批量的方式来卸载数据。

有关本文涉及到的参考链接:
    SQL*Loader使用方法 
    数据泵 EXPDP 导出工具的使用    数据泵IMPDP 导入工具的使用    PL/SQL-->UTL_FILE包的使用介绍

1、单表卸载数据

  1. --首先查看你的数据库是否存在相应的dump目录,如果没有,则应先使用create or replace directory dir_name as '/yourpath'创建
  2. scott@SYBO2SZ> @dba_directories
  3. Owner      Directory Name                 Directory Path
  4. ---------- ------------------------------ -------------------------------------------------
  5. SYS        DB_DUMP_DIR                    /u02/database/SYBO2SZ/BNR/dump
  6. --下面是用匿名的pl/sql块来卸载单表数据
  7. DECLARE
  8. l_rows   NUMBER;
  9. BEGIN
  10. l_rows :=
  11. unloader.run (p_query        => 'select * from scott.emp order by empno',    --->定义你的查询
  12. p_tname        => 'emp',                                       --->定义放入控制文件的表名
  13. p_mode         => 'replace',                                   --->定义装载到目标表时使用的方式
  14. p_dir          => 'DB_DUMP_DIR',                               --->定义卸载数据存放目录
  15. p_filename     => 'emp',                                       --->定义生成的文件名
  16. p_separator    => ',',                                         --->字段分隔符
  17. p_enclosure    => '"',                                         --->封装每个字段的符合
  18. p_terminator   => '~');                                        --->行终止符
  19. DBMS_OUTPUT.put_line (TO_CHAR (l_rows) || ' rows extracted to ascii file');
  20. END;
  21. /
  22. 14 rows extracted to ascii file
  23. PL/SQL procedure successfully completed.
  24. --查看刚刚卸载数据生成的文件
  25. scott@SYBO2SZ> ho ls -hltr /u02/database/SYBO2SZ/BNR/dump
  26. total 8.0K
  27. -rw-r--r-- 1 oracle oinstall  913 2014-01-14 15:04 emp.dat
  28. -rw-r--r-- 1 oracle oinstall  261 2014-01-14 15:04 emp.ctl
  29. --查看卸载文件的内容
  30. scott@SYBO2SZ> ho more /u02/database/SYBO2SZ/BNR/dump/emp.dat
  31. "7369","SMITH","CLERK","7902","17121980000000","800","","20"~
  32. "7499","ALLEN","SALESMAN","7698","20021981000000","1600","300","30"~
  33. "7521","WARD","SALESMAN","7698","22021981000000","1250","500","30"~
  34. "7566","JONES","MANAGER","7839","02041981000000","2975","","20"~
  35. "7654","MARTIN","SALESMAN","7698","28091981000000","1250","1400","30"~
  36. "7698","BLAKE","MANAGER","7839","01051981000000","2850","","30"~
  37. "7782","CLARK","MANAGER","7839","09061981000000","2650","","10"~
  38. "7788","SCOTT","ANALYST","7566","19041987000000","3000","","20"~
  39. "7839","KING","PRESIDENT","","17111981000000","5200","","10"~
  40. "7844","TURNER","SALESMAN","7698","08091981000000","1500","0","30"~
  41. "7876","ADAMS","CLERK","7788","23051987000000","1100","","20"~
  42. "7900","JAMES","CLERK","7698","03121981000000","950","","30"~
  43. "7902","FORD","ANALYST","7566","03121981000000","3000","","20"~
  44. "7934","MILLER","CLERK","7782","23011982000000","1500","","10"~
  45. --下面是生成的控制文件,有了数据文件和控制文件可以直接进行导入目标表
  46. scott@SYBO2SZ> ho more /u02/database/SYBO2SZ/BNR/dump/emp.ctl
  47. load data
  48. infile 'emp.dat' "str x'7E0A'"
  49. into table emp
  50. replace
  51. fields terminated by X'2c' enclosed by X'22'
  52. (
  53. EMPNO char(44 ),
  54. ENAME char(20 ),
  55. JOB char(18 ),
  56. MGR char(44 ),
  57. HIREDATE date 'ddmmyyyyhh24miss' ,
  58. SAL char(44 ),
  59. COMM char(44 ),
  60. DEPTNO char(44 )
  61. )
  62. --下面我们先truncate表emp,然后尝试使用sqlldr来装载数据
  63. scott@SYBO2SZ> truncate table emp;
  64. Table truncated.
  65. --装载数据到emp
  66. robin@SZDB:/u02/database/SYBO2SZ/BNR/dump> sqlldr scott/tiger control=emp.ctl data=emp.dat direct=true
  67. SQL*Loader: Release 10.2.0.3.0 - Production on Tue Jan 14 15:45:39 2014
  68. Copyright (c) 1982, 2005, Oracle.  All rights reserved.
  69. Load completed - logical record count 14.

2、批量卸载数据

  1. --使用下面的匿名pl/sql块可以实现批量卸载数据,此处不演示
  2. DECLARE
  3. l_rows   NUMBER;
  4. v_sql    VARCHAR2 (200);
  5. CURSOR cur_tab
  6. IS
  7. SELECT table_name FROM user_tables;-->这里定义需要卸载的表,可以单独指定一个表用于存放需要卸载的对象,此处直接查询数据字典
  8. BEGIN
  9. FOR tab_name IN cur_tab
  10. LOOP
  11. v_sql := 'select * from ' || tab_name.table_name;
  12. l_rows :=
  13. unloader.run (p_query        => v_sql,
  14. p_tname        => tab_name.table_name,
  15. p_mode         => 'replace',
  16. p_dir          => 'DB_DUMP_DIR',
  17. p_filename     => tab_name.table_name,
  18. p_separator    => ',',
  19. p_enclosure    => '"',
  20. p_terminator   => '~');
  21. -- Author : Leshami
  22. -- Blog   : http://blog.csdn.net/leshami
  23. DBMS_OUTPUT.put_line (TO_CHAR (l_rows) || ' rows extracted to ascii file');
  24. END LOOP;
  25. END;
  26. /

3、卸载数据原始脚本

  1. robin@SZDB:~/dba_scripts/custom/tom> more unloader_pkg.sql
  2. CREATE OR REPLACE PACKAGE unloader
  3. AUTHID CURRENT_USER
  4. AS
  5. /* Function run -- unloads data from any query into a file
  6. and creates a control file to reload that
  7. data into another table
  8. --注释信息给出了比较详细的描述
  9. p_query = SQL query to "unload". May be virtually any query.
  10. p_tname = Table to load into. Will be put into control file.
  11. p_mode = REPLACE|APPEND|TRUNCATE -- how to reload the data
  12. p_dir = directory we will write the ctl and dat file to.
  13. p_filename = name of file to write to. I will add .ctl and .dat
  14. to this name
  15. p_separator = field delimiter. I default this to a comma.
  16. p_enclosure = what each field will be wrapped in
  17. p_terminator = end of line character. We use this so we can unload
  18. and reload data with newlines in it. I default to
  19. "|\n" (a pipe and a newline together) and "|\r\n" on NT.
  20. You need only to override this if you believe your
  21. data will have that sequence in it. I ALWAYS add the
  22. OS "end of line" marker to this sequence, you should not
  23. */
  24. FUNCTION run (p_query        IN VARCHAR2,
  25. p_tname        IN VARCHAR2,
  26. p_mode         IN VARCHAR2 DEFAULT 'REPLACE',
  27. p_dir          IN VARCHAR2,
  28. p_filename     IN VARCHAR2,
  29. p_separator    IN VARCHAR2 DEFAULT ',',
  30. p_enclosure    IN VARCHAR2 DEFAULT '"',
  31. p_terminator   IN VARCHAR2 DEFAULT '|')
  32. RETURN NUMBER;
  33. END;
  34. /
  35. CREATE OR REPLACE PACKAGE BODY unloader
  36. AS
  37. g_thecursor   INTEGER DEFAULT DBMS_SQL.open_cursor;
  38. g_desctbl     DBMS_SQL.desc_tab;
  39. g_nl          VARCHAR2 (2) DEFAULT CHR (10);
  40. FUNCTION to_hex (p_str IN VARCHAR2)
  41. RETURN VARCHAR2
  42. IS
  43. BEGIN
  44. RETURN TO_CHAR (ASCII (p_str), 'fm0x');
  45. END;
  46. FUNCTION is_windows
  47. RETURN BOOLEAN
  48. IS
  49. l_cfiles   VARCHAR2 (4000);
  50. l_dummy    NUMBER;
  51. BEGIN
  52. IF (DBMS_UTILITY.get_parameter_value ('control_files', l_dummy, l_cfiles) > 0)
  53. THEN
  54. RETURN INSTR (l_cfiles, '\') > 0;
  55. ELSE
  56. RETURN FALSE;
  57. END IF;
  58. END;
  59. PROCEDURE dump_ctl (p_dir          IN VARCHAR2,
  60. p_filename     IN VARCHAR2,
  61. p_tname        IN VARCHAR2,
  62. p_mode         IN VARCHAR2,
  63. p_separator    IN VARCHAR2,
  64. p_enclosure    IN VARCHAR2,
  65. p_terminator   IN VARCHAR2)
  66. IS
  67. l_output   UTL_FILE.file_type;
  68. l_sep      VARCHAR2 (5);
  69. l_str      VARCHAR2 (5) := CHR (10);
  70. BEGIN
  71. IF (is_windows)
  72. THEN
  73. l_str := CHR (13) || CHR (10);
  74. END IF;
  75. l_output := UTL_FILE.fopen (p_dir, p_filename || '.ctl', 'w');
  76. UTL_FILE.put_line (l_output, 'load data');
  77. UTL_FILE.put_line (l_output, 'infile ''' || p_filename || '.dat'' "str x''' || UTL_RAW.cast_to_raw (p_terminator || l_str) || '''"');
  78. UTL_FILE.put_line (l_output, 'into table ' || p_tname);
  79. UTL_FILE.put_line (l_output, p_mode);
  80. UTL_FILE.put_line (l_output, 'fields terminated by X''' || to_hex (p_separator) || ''' enclosed by X''' || to_hex (p_enclosure) || ''' ');
  81. UTL_FILE.put_line (l_output, '(');
  82. FOR i IN 1 .. g_desctbl.COUNT
  83. LOOP
  84. IF (g_desctbl (i).col_type = 12)
  85. THEN
  86. UTL_FILE.put (l_output, l_sep || g_desctbl (i).col_name || ' date ''ddmmyyyyhh24miss'' ');
  87. ELSE
  88. UTL_FILE.put (l_output, l_sep || g_desctbl (i).col_name || ' char(' || TO_CHAR (g_desctbl (i).col_max_len * 2) || ' )');
  89. END IF;
  90. l_sep := ',' || g_nl;
  91. END LOOP;
  92. UTL_FILE.put_line (l_output, g_nl || ')');
  93. UTL_FILE.fclose (l_output);
  94. END;
  95. FUNCTION quote (p_str IN VARCHAR2, p_enclosure IN VARCHAR2)
  96. RETURN VARCHAR2
  97. IS
  98. BEGIN
  99. RETURN p_enclosure || REPLACE (p_str, p_enclosure, p_enclosure || p_enclosure) || p_enclosure;
  100. END;
  101. FUNCTION run (p_query        IN VARCHAR2,
  102. p_tname        IN VARCHAR2,
  103. p_mode         IN VARCHAR2 DEFAULT 'REPLACE',
  104. p_dir          IN VARCHAR2,
  105. p_filename     IN VARCHAR2,
  106. p_separator    IN VARCHAR2 DEFAULT ',',
  107. p_enclosure    IN VARCHAR2 DEFAULT '"',
  108. p_terminator   IN VARCHAR2 DEFAULT '|')
  109. RETURN NUMBER
  110. IS
  111. l_output        UTL_FILE.file_type;
  112. l_columnvalue   VARCHAR2 (4000);
  113. l_colcnt        NUMBER DEFAULT 0;
  114. l_separator     VARCHAR2 (10) DEFAULT '';
  115. l_cnt           NUMBER DEFAULT 0;
  116. l_line          LONG;
  117. l_datefmt       VARCHAR2 (255);
  118. l_desctbl       DBMS_SQL.desc_tab;
  119. BEGIN
  120. SELECT VALUE
  121. INTO l_datefmt
  122. FROM nls_session_parameters
  123. WHERE parameter = 'NLS_DATE_FORMAT';
  124. /*
  125. Set the date format to a big numeric string. Avoids
  126. all NLS issues and saves both the time and date.
  127. */
  128. EXECUTE IMMEDIATE 'alter session set nls_date_format=''ddmmyyyyhh24miss'' ';
  129. /*
  130. Set up an exception block so that in the event of any
  131. error, we can at least reset the date format.
  132. */
  133. BEGIN
  134. /*
  135. Parse and describe the query. We reset the
  136. descTbl to an empty table so .count on it
  137. will be reliable.
  138. */
  139. DBMS_SQL.parse (g_thecursor, p_query, DBMS_SQL.native);
  140. g_desctbl := l_desctbl;
  141. DBMS_SQL.describe_columns (g_thecursor, l_colcnt, g_desctbl);
  142. /*
  143. Create a control file to reload this data
  144. into the desired table.
  145. */
  146. dump_ctl (p_dir,
  147. p_filename,
  148. p_tname,
  149. p_mode,
  150. p_separator,
  151. p_enclosure,
  152. p_terminator);
  153. /*
  154. Bind every single column to a varchar2(4000). We don't care
  155. if we are fetching a number or a date or whatever.
  156. Everything can be a string.
  157. */
  158. FOR i IN 1 .. l_colcnt
  159. LOOP
  160. DBMS_SQL.define_column (g_thecursor,
  161. i,
  162. l_columnvalue,
  163. 4000);
  164. END LOOP;
  165. /*
  166. Run the query - ignore the output of execute. It is only
  167. valid when the DML is an insert/update or delete.
  168. */
  169. l_cnt := DBMS_SQL.execute (g_thecursor);
  170. /*
  171. Open the file to write output to and then write the
  172. delimited data to it.
  173. */
  174. l_output :=
  175. UTL_FILE.fopen (p_dir,
  176. p_filename || '.dat',
  177. 'w',
  178. 32760);
  179. LOOP
  180. EXIT WHEN (DBMS_SQL.fetch_rows (g_thecursor) <= 0);
  181. l_separator := '';
  182. l_line := NULL;
  183. FOR i IN 1 .. l_colcnt
  184. LOOP
  185. DBMS_SQL.COLUMN_VALUE (g_thecursor, i, l_columnvalue);
  186. l_line := l_line || l_separator || quote (l_columnvalue, p_enclosure);
  187. l_separator := p_separator;
  188. END LOOP;
  189. l_line := l_line || p_terminator;
  190. UTL_FILE.put_line (l_output, l_line);
  191. l_cnt := l_cnt + 1;
  192. END LOOP;
  193. UTL_FILE.fclose (l_output);
  194. /*
  195. Now reset the date format and return the number of rows
  196. written to the output file.
  197. */
  198. EXECUTE IMMEDIATE 'alter session set nls_date_format=''' || l_datefmt || '''';
  199. RETURN l_cnt;
  200. EXCEPTION
  201. /*
  202. In the event of ANY error, reset the data format and
  203. re-raise the error.
  204. */
  205. WHEN OTHERS
  206. THEN
  207. EXECUTE IMMEDIATE 'alter session set nls_date_format=''' || l_datefmt || '''';
  208. RAISE;
  209. END;
  210. END run;
  211. END unloader;
  212. /

4、小结
a、本文描述了单表以及多表如何高速卸载数据,并且批量生成sqlldr的控制文件及数据文件
b、包调用者应该对unloader其具有execute权限以及表上的select权限
c、包主要是通过utl_file来写出到控制文件和数据文件,有关utl_file用法可参考:PL/SQL-->UTL_FILE包的使用介绍 
d、Tom大师的这个包支持lob数据类型,但其字节不能大于4000,以及不支持long raw

转:http://blog.csdn.net/leshami/article/details/18266003

批量生成sqlldr文件,高速卸载数据的更多相关文章

  1. [原创] 利用前端+php批量生成html文件,传入新文本,输出新的html文件

    本人因为要想自己写个小说网站练练手,在其中遇到的一些问题,将其解决方法总结出来,例如: 1:小说网站存储了大量的小说,每个小说主页都很相似,url不同,不是使用的history属性改写的,所以如果人工 ...

  2. FluentData-新型轻量级ORM 利用T4模板 批量生成多文件 实体和业务逻辑 代码

    FluentData,它是一个轻量级框架,关注性能和易用性. 下载地址:FlunenData.Model 利用T4模板,[MultipleOutputHelper.ttinclude]批量生成多文件 ...

  3. python xlwt模块生成excel文件并写入数据 xlrd读取数据

    python中一般使用 xlwt (excel write)来生成Excel文件(可以控制单元格格式),用 xlrd 来读取Excel文件,用xlrd读取excel是不能对其进行操作的. 1.xlrd ...

  4. T4模板批量生成代码文件

    <#@ template debug="false" hostspecific="true" language="C#" #> ...

  5. T4批量生成多文件

    http://www.cnblogs.com/zengxiangzhan/p/3250105.html Manager.ttinclude <#@ assembly name="Sys ...

  6. 生成HFile文件后倒入数据出现Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.hbase.filter.Filter

    数据导入的时候出现: at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclar ...

  7. asp.net asp.net application 升级到 asp.net web 解决找不到控件 批量生成.designer文件

    颇费周折后,其实很简单,只需要生成designer文件后,重新保存所有页面即可.就是懒得写.懒真的是一种病,手上不能懒,脑子里更不能懒,否则就是给自己挖坑,仔细认真,注意细节!!!! PS:注意修改p ...

  8. 批量生成xml文件数据C#实现

    方法一 // < Records count = "5" > //< Record > // < Contact_ID > 5 - 55W - ...

  9. 利用Resgen.exe 批量生成resources文件

    Resgen.exe(资源文件生成器)  您可以直接如图操作 转换时在 文本中先写好要转换的文件然后 全选 复制到控制台中 Filename.resx 要转换的文件 ResName1.resource ...

随机推荐

  1. Understanding node.js

    Node.js has generally caused two reactions in people I've introduced it to. Basically people either ...

  2. 妙味课堂——HTML+CSS(第二课)

    常见标签——img标签 <img src="图片地址" alt="图片名"/> alt属性是图片名字,是给百度搜索引擎抓取使用的.也有当图片地址不正 ...

  3. IDA 使用技巧

    我用的IDA Pro 6.5,把我自己使用ida的一些方法记录,免得自己遗忘 1 .导入符号表 可以像前一篇博客中写的那样,也可以使用File--->LoadFile--->PDB Fil ...

  4. linux下如何查看主机的外网ip地址

    在linux下如果我们使用的是nat方式上网.通过ifconfig命令查看到的ip地址往往是内网地址 那么如何查看主机在互联网上使用的公网IP呢?我们可以在命令行下使用curl命令实现这个功能. [r ...

  5. MongoDB 管理工具:Robomongo

    http://www.open-open.com/lib/view/open1383029577546.html

  6. lintcode: 最长连续序列

    最长连续序列 给定一个未排序的整数数组,找出最长连续序列的长度. 说明 要求你的算法复杂度为O(n) 样例 给出数组[100, 4, 200, 1, 3, 2],这个最长的连续序列是 [1, 2, 3 ...

  7. ios开发 ad hoc

    iOS证书分2种,1种是开发证书,用来给你(开发人员)做真机测试的:1种是发布证书,发布证书又分发布到app store的(这里不提及)和发布测试的ad hoc证书. 那ad hoc证书和开发证书区别 ...

  8. Java学习笔记之:Java 内部类

    一.介绍 内部类:存在与类中的类就是内部类,一般用于Android开发. 可以把内部类理解成一种继承关系 1.普通内部类 2.局部内部类 3.静态内部类 4.匿名内部类 二.笔记 1.普通内部类 /* ...

  9. SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-001-使用Hibernate(@Inject、@EnableTransactionManagement、@Repository、PersistenceExceptionTranslationPostProcessor)

    一.结构 二.Repository层 1. package spittr.db; import java.util.List; import spittr.domain.Spitter; /** * ...

  10. 关于LINUX权限-bash: ./startup.sh: Permission denied

    关于LINUX权限-bash: ./startup.sh: Permission denied <script type="text/javascript"></ ...