oracle平面文件卸载
Posted xuzhong86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle平面文件卸载相关的知识,希望对你有一定的参考价值。
-- Flat File Unload create or replace package unloader AUTHID CURRENT_USER as /* 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 default sequence of characters 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 unloader as 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 date 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; /
set serveroutput on create or replace directory MY_DIR as ‘/home/oracle/backup‘;--创建目录 grant read,write on directory MY_DIR to public;--对所有用户赋上个目录的读写权限 -----drop directory MY_DIR;
运行下面代码将卸载scott下的emp表到MY_DIR下,分别生成ctl和dat文件
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 => ‘MY_DIR‘, p_filename => ‘emp‘, p_separator => ‘,‘, p_enclosure => ‘"‘, p_terminator => ‘~‘ ); dbms_output.put_line( to_char(l_rows) || ‘ rows extracted to ascii file‘ ); end; /