批量生成sqlldr文件,高速卸载数据
来源:互联网 发布:广东广播网络电视台 编辑:程序博客网 时间:2024/04/27 16:36
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、单表卸载数据
--首先查看你的数据库是否存在相应的dump目录,如果没有,则应先使用create or replace directory dir_name as '/yourpath'创建scott@SYBO2SZ> @dba_directoriesOwner Directory Name Directory Path---------- ------------------------------ -------------------------------------------------SYS DB_DUMP_DIR /u02/database/SYBO2SZ/BNR/dump--下面是用匿名的pl/sql块来卸载单表数据DECLARE l_rows NUMBER;BEGIN l_rows := unloader.run (p_query => 'select * from scott.emp order by empno', --->定义你的查询 p_tname => 'emp', --->定义放入控制文件的表名 p_mode => 'replace', --->定义装载到目标表时使用的方式 p_dir => 'DB_DUMP_DIR', --->定义卸载数据存放目录 p_filename => 'emp', --->定义生成的文件名 p_separator => ',', --->字段分隔符 p_enclosure => '"', --->封装每个字段的符合 p_terminator => '~'); --->行终止符 DBMS_OUTPUT.put_line (TO_CHAR (l_rows) || ' rows extracted to ascii file');END;/14 rows extracted to ascii filePL/SQL procedure successfully completed.--查看刚刚卸载数据生成的文件scott@SYBO2SZ> ho ls -hltr /u02/database/SYBO2SZ/BNR/dumptotal 8.0K-rw-r--r-- 1 oracle oinstall 913 2014-01-14 15:04 emp.dat-rw-r--r-- 1 oracle oinstall 261 2014-01-14 15:04 emp.ctl--查看卸载文件的内容 scott@SYBO2SZ> ho more /u02/database/SYBO2SZ/BNR/dump/emp.dat"7369","SMITH","CLERK","7902","17121980000000","800","","20"~"7499","ALLEN","SALESMAN","7698","20021981000000","1600","300","30"~"7521","WARD","SALESMAN","7698","22021981000000","1250","500","30"~"7566","JONES","MANAGER","7839","02041981000000","2975","","20"~"7654","MARTIN","SALESMAN","7698","28091981000000","1250","1400","30"~"7698","BLAKE","MANAGER","7839","01051981000000","2850","","30"~"7782","CLARK","MANAGER","7839","09061981000000","2650","","10"~"7788","SCOTT","ANALYST","7566","19041987000000","3000","","20"~"7839","KING","PRESIDENT","","17111981000000","5200","","10"~"7844","TURNER","SALESMAN","7698","08091981000000","1500","0","30"~"7876","ADAMS","CLERK","7788","23051987000000","1100","","20"~"7900","JAMES","CLERK","7698","03121981000000","950","","30"~"7902","FORD","ANALYST","7566","03121981000000","3000","","20"~"7934","MILLER","CLERK","7782","23011982000000","1500","","10"~--下面是生成的控制文件,有了数据文件和控制文件可以直接进行导入目标表scott@SYBO2SZ> ho more /u02/database/SYBO2SZ/BNR/dump/emp.ctlload datainfile 'emp.dat' "str x'7E0A'"into table empreplacefields terminated by X'2c' enclosed by X'22' (EMPNO char(44 ),ENAME char(20 ),JOB char(18 ),MGR char(44 ),HIREDATE date 'ddmmyyyyhh24miss' ,SAL char(44 ),COMM char(44 ),DEPTNO char(44 ))--下面我们先truncate表emp,然后尝试使用sqlldr来装载数据scott@SYBO2SZ> truncate table emp;Table truncated.--装载数据到emprobin@SZDB:/u02/database/SYBO2SZ/BNR/dump> sqlldr scott/tiger control=emp.ctl data=emp.dat direct=trueSQL*Loader: Release 10.2.0.3.0 - Production on Tue Jan 14 15:45:39 2014Copyright (c) 1982, 2005, Oracle. All rights reserved.Load completed - logical record count 14.
2、批量卸载数据
--使用下面的匿名pl/sql块可以实现批量卸载数据,此处不演示DECLARE l_rows NUMBER; v_sql VARCHAR2 (200); CURSOR cur_tab IS SELECT table_name FROM user_tables;-->这里定义需要卸载的表,可以单独指定一个表用于存放需要卸载的对象,此处直接查询数据字典BEGIN FOR tab_name IN cur_tab LOOP v_sql := 'select * from ' || tab_name.table_name; l_rows := unloader.run (p_query => v_sql, p_tname => tab_name.table_name, p_mode => 'replace', p_dir => 'DB_DUMP_DIR', p_filename => tab_name.table_name, p_separator => ',', p_enclosure => '"', p_terminator => '~');-- Author : Leshami-- Blog : http://blog.csdn.net/leshami DBMS_OUTPUT.put_line (TO_CHAR (l_rows) || ' rows extracted to ascii file'); END LOOP;END;/
3、卸载数据原始脚本
robin@SZDB:~/dba_scripts/custom/tom> more unloader_pkg.sql CREATE OR REPLACE PACKAGE unloader AUTHID CURRENT_USERAS /* Function run -- unloads data from any query into a file and creates a control file to reload that data into another table --注释信息给出了比较详细的描述 p_query = SQL query to "unload". May be virtually any query. p_tname = Table to load into. Will be put into control file. p_mode = REPLACE|APPEND|TRUNCATE -- how to reload the data p_dir = directory we will write the ctl and dat file to. p_filename = name of file to write to. I will add .ctl and .dat to this name p_separator = field delimiter. I default this to a comma. p_enclosure = what each field will be wrapped in p_terminator = end of line character. We use this so we can unload and reload data with newlines in it. I default to "|\n" (a pipe and a newline together) and "|\r\n" on NT. You need only to override this if you believe your data will have that sequence in it. I ALWAYS add the OS "end of line" marker to this sequence, you should not */ FUNCTION run (p_query IN VARCHAR2, p_tname IN VARCHAR2, p_mode IN VARCHAR2 DEFAULT 'REPLACE', p_dir IN VARCHAR2, p_filename IN VARCHAR2, p_separator IN VARCHAR2 DEFAULT ',', p_enclosure IN VARCHAR2 DEFAULT '"', p_terminator IN VARCHAR2 DEFAULT '|') RETURN NUMBER;END;/CREATE OR REPLACE PACKAGE BODY unloaderAS g_thecursor INTEGER DEFAULT DBMS_SQL.open_cursor; g_desctbl DBMS_SQL.desc_tab; g_nl VARCHAR2 (2) DEFAULT CHR (10); FUNCTION to_hex (p_str IN VARCHAR2) RETURN VARCHAR2 IS BEGIN RETURN TO_CHAR (ASCII (p_str), 'fm0x'); END; FUNCTION is_windows RETURN BOOLEAN IS l_cfiles VARCHAR2 (4000); l_dummy NUMBER; BEGIN IF (DBMS_UTILITY.get_parameter_value ('control_files', l_dummy, l_cfiles) > 0) THEN RETURN INSTR (l_cfiles, '\') > 0; ELSE RETURN FALSE; END IF; END; PROCEDURE dump_ctl (p_dir IN VARCHAR2, p_filename IN VARCHAR2, p_tname IN VARCHAR2, p_mode IN VARCHAR2, p_separator IN VARCHAR2, p_enclosure IN VARCHAR2, p_terminator IN VARCHAR2) IS l_output UTL_FILE.file_type; l_sep VARCHAR2 (5); l_str VARCHAR2 (5) := CHR (10); BEGIN IF (is_windows) THEN l_str := CHR (13) || CHR (10); END IF; l_output := UTL_FILE.fopen (p_dir, p_filename || '.ctl', 'w'); UTL_FILE.put_line (l_output, 'load data'); UTL_FILE.put_line (l_output, 'infile ''' || p_filename || '.dat'' "str x''' || UTL_RAW.cast_to_raw (p_terminator || l_str) || '''"'); UTL_FILE.put_line (l_output, 'into table ' || p_tname); UTL_FILE.put_line (l_output, p_mode); UTL_FILE.put_line (l_output, 'fields terminated by X''' || to_hex (p_separator) || ''' enclosed by X''' || to_hex (p_enclosure) || ''' '); UTL_FILE.put_line (l_output, '('); FOR i IN 1 .. g_desctbl.COUNT LOOP IF (g_desctbl (i).col_type = 12) THEN UTL_FILE.put (l_output, l_sep || g_desctbl (i).col_name || ' date ''ddmmyyyyhh24miss'' '); ELSE UTL_FILE.put (l_output, l_sep || g_desctbl (i).col_name || ' char(' || TO_CHAR (g_desctbl (i).col_max_len * 2) || ' )'); END IF; l_sep := ',' || g_nl; END LOOP; UTL_FILE.put_line (l_output, g_nl || ')'); UTL_FILE.fclose (l_output); END; FUNCTION quote (p_str IN VARCHAR2, p_enclosure IN VARCHAR2) RETURN VARCHAR2 IS BEGIN RETURN p_enclosure || REPLACE (p_str, p_enclosure, p_enclosure || p_enclosure) || p_enclosure; END; FUNCTION run (p_query IN VARCHAR2, p_tname IN VARCHAR2, p_mode IN VARCHAR2 DEFAULT 'REPLACE', p_dir IN VARCHAR2, p_filename IN VARCHAR2, p_separator IN VARCHAR2 DEFAULT ',', p_enclosure IN VARCHAR2 DEFAULT '"', p_terminator IN VARCHAR2 DEFAULT '|') RETURN NUMBER IS l_output UTL_FILE.file_type; l_columnvalue VARCHAR2 (4000); l_colcnt NUMBER DEFAULT 0; l_separator VARCHAR2 (10) DEFAULT ''; l_cnt NUMBER DEFAULT 0; l_line LONG; l_datefmt VARCHAR2 (255); l_desctbl DBMS_SQL.desc_tab; BEGIN SELECT VALUE INTO l_datefmt FROM nls_session_parameters WHERE parameter = 'NLS_DATE_FORMAT'; /* Set the date format to a big numeric string. Avoids all NLS issues and saves both the time and date. */ EXECUTE IMMEDIATE 'alter session set nls_date_format=''ddmmyyyyhh24miss'' '; /* Set up an exception block so that in the event of any error, we can at least reset the date format. */ BEGIN /* Parse and describe the query. We reset the descTbl to an empty table so .count on it will be reliable. */ DBMS_SQL.parse (g_thecursor, p_query, DBMS_SQL.native); g_desctbl := l_desctbl; DBMS_SQL.describe_columns (g_thecursor, l_colcnt, g_desctbl); /* Create a control file to reload this data into the desired table. */ dump_ctl (p_dir, p_filename, p_tname, p_mode, p_separator, p_enclosure, p_terminator); /* Bind every single column to a varchar2(4000). We don't care if we are fetching a number or a date or whatever. Everything can be a string. */ FOR i IN 1 .. l_colcnt LOOP DBMS_SQL.define_column (g_thecursor, i, l_columnvalue, 4000); END LOOP; /* Run the query - ignore the output of execute. It is only valid when the DML is an insert/update or delete. */ l_cnt := DBMS_SQL.execute (g_thecursor); /* Open the file to write output to and then write the delimited data to it. */ l_output := UTL_FILE.fopen (p_dir, p_filename || '.dat', 'w', 32760); LOOP EXIT WHEN (DBMS_SQL.fetch_rows (g_thecursor) <= 0); l_separator := ''; l_line := NULL; FOR i IN 1 .. l_colcnt LOOP DBMS_SQL.COLUMN_VALUE (g_thecursor, i, l_columnvalue); l_line := l_line || l_separator || quote (l_columnvalue, p_enclosure); l_separator := p_separator; END LOOP; l_line := l_line || p_terminator; UTL_FILE.put_line (l_output, l_line); l_cnt := l_cnt + 1; END LOOP; UTL_FILE.fclose (l_output); /* Now reset the date format and return the number of rows written to the output file. */ EXECUTE IMMEDIATE 'alter session set nls_date_format=''' || l_datefmt || ''''; RETURN l_cnt; EXCEPTION /* In the event of ANY error, reset the data format and re-raise the error. */ WHEN OTHERS THEN EXECUTE IMMEDIATE 'alter session set nls_date_format=''' || l_datefmt || ''''; RAISE; END; END run;END unloader;/
4、小结
a、本文描述了单表以及多表如何高速卸载数据,并且批量生成sqlldr的控制文件及数据文件
b、包调用者应该对unloader其具有execute权限以及表上的select权限
c、包主要是通过utl_file来写出到控制文件和数据文件,有关utl_file用法可参考:PL/SQL-->UTL_FILE包的使用介绍
d、Tom大师的这个包支持lob数据类型,但其字节不能大于4000,以及不支持long raw
更多参考
使用 DBMS_PROFILER 定位 PL/SQL 瓶颈代码
使用PL/SQL Developer剖析PL/SQL代码
对比 PL/SQL profiler 剖析结果
PL/SQL Profiler 剖析报告生成html
DML Error Logging 特性
PL/SQL --> 游标
PL/SQL --> 隐式游标(SQL%FOUND)
批量SQL之 FORALL 语句
批量SQL之 BULK COLLECT 子句
PL/SQL 集合的初始化与赋值
PL/SQL 联合数组与嵌套表
PL/SQL 变长数组
PL/SQL --> PL/SQL记录
SQL tuning 步骤
高效SQL语句必杀技
父游标、子游标及共享游标
绑定变量及其优缺点
dbms_xplan之display_cursor函数的使用
dbms_xplan之display函数的使用
执行计划中各字段各模块描述
使用 EXPLAIN PLAN 获取SQL语句执行计划
- 批量生成sqlldr文件,高速卸载数据
- sqlldr(sqlload)批量处理文件
- mysql高速批量导入数据
- Oracle sqlldr批量导入数据常见问题解决
- sqlldr批量导入数据到Oracle
- sqlldr批量导入文件夹下多个csv文件
- Oracle 高速批量速插入数据 解决方案
- Linux主机sqlldr工具批量文本数据导入oracle数据库
- oracle下的sqlldr命令使用方法(sqlldr工具的使用(批量导入数据))
- oracle下的sqlldr命令使用方法(sqlldr工具的使用(批量导入数据))
- 在oracle中 生成大规模数据 500万条 (使用导入数据方式 sqlldr 导入命令 *.ctl文件)
- 【postgresql】批量生成数据
- 使用SQL*Loader高速批量数据加载工具!
- 批量生成ISO文件
- 生成批量文件脚本
- 批量生成资源文件
- dos下批量卸载apk文件
- dos下批量卸载apk文件
- java设计模式学习
- 使用海康摄像头实现实时监控
- Unity3d怎么嵌入抓猫平台广告
- “惊群”,看看nginx是怎么解决它的
- iOS Objective-C 解析XML SAX解析方法
- 批量生成sqlldr文件,高速卸载数据
- 常见小波变换开源代码
- 方法重载的学习
- 博弈论基础
- shell中if做比较
- cocos2d-x CCMotionStreak 拖拽渐隐效果(切水果的刀?)
- 转身就要离去,正在这时
- MYSQL常用备份命令收集
- 卷积运算