Oracle Script to unload/load a table
This script will generate a script to unload a table to a file and a SQL*Loader script to reload the same data. Intent is to create a faster alternative to export/import.
set tab off
set heading off heading off feedback off echo off verify off space 1 pagesize 0 linesize 120
accept owner prompt 'What schema owns the table to be unloaded? '
accept table_name prompt 'What table is to be unloaded? '
accept default_precision prompt 'What TOTAL number of digits should be reserved for numbers without defined precision? '
accept default_scale prompt 'What number of DECIMAL digits should be reserved for numbers without defined scale? '
---------------------------------------------------
-- Generate the unload script
---------------------------------------------------
spool unload_table . sql
select 'SET HEADING OFF FEEDBACK OFF ECHO OFF VERIFY OFF SPACE 0 PAGESIZE 0 TERMOUT OFF'
from dual
/
-- Calculate the sum of all output field lengths and set the output record size
select 'SET LINESIZE '
|| ( sum ( decode ( data_type ,
'CHAR' , data_length ,
'VARCHAR' , data_length ,
'VARCHAR2' , data_length ,
'DATE' , 14 ,
'NUMBER' , decode ( data_precision ,
'' , & default_precision + 2 ,
greatest ( data_precision - data_scale , 1 ) + decode ( data_scale , 0 , 0 , 1 ) + data_scale ) + 1 ,
'FLOAT' , & default_precision + 2 ,
data_length )))
from dba_tab_columns
where owner = upper ( '&&owner' )
and table_name = upper ( '&&table_name' )
/
-- Generate an appropriate SQL*Plus COLUMN command to control formatting of each output field
select 'COLUMN ' || rpad ( '"' || column_name || '"' , 32 )
|| ' FORMAT '
|| rpad ( decode ( data_type ,
'CHAR' , 'A' || data_length ,
'VARCHAR2' , 'A' || data_length ,
'VARCHAR' , 'A' || data_length ,
'DATE' , 'A14' ,
'NUMBER' , decode ( data_precision ,
'' , rpad ( '0' , & default_precision -& default_scale , '9' ) || '.' || rpad ( '9' , & default_scale , '9' ),
rpad ( '0' , greatest ( data_precision - data_scale , 1 ), '9' ) || decode ( data_scale , 0 , '' , '.' )
|| decode ( data_scale , 0 , '' , rpad ( '9' , data_scale , '9' ))),
'FLOAT' , rpad ( '0' , & default_precision -& default_scale , '9' ) || '.' || rpad ( '9' , & default_scale , '9' ),
'ERROR' ), 40 )
|| ' HEADING '' X '' '
from dba_tab_columns
where owner = upper ( '&&owner' )
and table_name = upper ( '&&table_name' )
order by column_id
/
-- Generate the actual SELECT statement to unload table data
select 'SPOOL /tmp/&&owner..&&table_name..DAT'
from dual
/
column var1 noprint
column var2 noprint
select 'a' var1 , 0 var2 , 'SELECT '
from dual
union
select 'b' , column_id , decode ( column_id , 1 , ' ' , ' , ' )
|| decode ( data_type , 'DATE' , 'to_char(' || '"' || column_name || '"' || ', '' YYYYMMDDHH24MISS '' ) ' || '"' || column_name || '"' ,
'"' || column_name || '"' )
from dba_tab_columns
where owner = upper ( '&&owner' )
and table_name = upper ( '&&table_name' )
union
select 'c' , 0 , 'FROM &&owner..&&table_name'
from dual
union
select 'd' , 0 , ';'
from dual
order by 1 , 2
/
select 'SPOOL OFF'
from dual
/
select 'SET TERMOUT ON'
from dual
/
spool off
-----------------------------------------------------------------------------
-- Generate the SQL*Loader control file
-----------------------------------------------------------------------------
set lines 120 pages 0
spool && owner .. && table_name .. CTL
select 'a' var1 , 0 var2 , 'OPTIONS(DIRECT=TRUE)'
from dual
union
select 'b' , 0 , 'LOAD DATA'
from dual
union
select 'c' , 0 , 'INFILE '' /tmp/&&owner..&&table_name..DAT '' '
from dual
union
select 'd' , 0 , 'BADFILE &&owner..&&table_name..BAD'
from dual
union
select 'e' , 0 , 'DISCARDFILE &&owner..&&table_name..DSC'
from dual
union
select 'f' , 0 , 'DISCARDMAX 999'
from dual
union
select 'm' , 0 , 'INTO TABLE &&owner..&&table_name'
from dual
union
select 'n' , column_id , rpad ( decode ( column_id , 1 , '(' , ',' ) || '"' || column_name || '"' , 31 )
|| decode ( data_type ,
'CHAR' , 'CHAR(' || data_length || ')' ,
'VARCHAR' , 'CHAR(' || data_length || ')' ,
'VARCHAR2' , 'CHAR(' || data_length || ')' ,
'DATE' , 'DATE(14) "YYYYMMDDHH24MISS"' ,
'NUMBER' , 'DECIMAL EXTERNAL(' || decode ( data_precision ,
'' , & default_precision + 2 ,
greatest ( data_precision - data_scale , 1 ) + decode ( data_scale , 0 , 0 , 1 ) + data_scale + 1 )
|| ')' ,
'FLOAT' , 'DECIMAL EXTERNAL(' || to_char ( & default_precision + 2 ) || ')' ,
'ERROR--' || data_type )
|| ' NULLIF ("' || column_name || '" = BLANKS)'
from dba_tab_columns
where owner = upper ( '&&owner' )
and table_name = upper ( '&&table_name' )
union
select 'z' , 0 , ')'
from dual
order by 1 , 2
/
spool off
-----------------------------------------------------------------------------
-- Cleanup
-----------------------------------------------------------------------------
clear column
clear break
clear compute
undef owner
undef table_name
undef default_precision
undef default_scale