sqlldr批量生成控制文件

參考文檔:http://askjoey.blog.51cto.com/7594056/1671852linux

環境:oracle11g,redhat linuxsql

1.創建基礎表oracle

create table TAB_COLUMN_UNION
(
  TAB_COLUMN_ORA    VARCHAR2(4000),
  TAB_COLUMN_SOURCE VARCHAR2(4000),
  TABLE_NAME        VARCHAR2(500)
)
tablespace SDATA
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 16
    next 8
    minextents 1
    maxextents unlimited
  );oop

table_name 中插入須要生成控制文件的表名。編碼

TAB_COLUMN_ORA 經過存儲過程生成表對應的每列spa

TAB_COLUMN_SOURCE 經過存儲過程生成導出成數據文件的語句,這裏假設源庫和目標庫都是oracleblog

存儲過程以下:utf-8

CREATE OR REPLACE PROCEDURE ETL_DOWNLOAD as



n_count integer;

v_column_ora varchar2(4000);


begin

update tab_column_union set tab_column_ora=null;

update tab_column_union set TAB_COLUMN_SOURCE=null;


for c1 in (select column_name,a.table_name,column_id,data_type from user_tables a,user_tab_columns b
  where a.table_name=b.TABLE_NAME and b.DATA_TYPE not in ('CLOB','BLOB') order by a.table_name,column_id)

loop

n_count:=0;

v_column_ora:=null;

select '''"''||'||c1.column_name||'||''"''' into v_column_ora from dual;

update tab_column_union set TAB_COLUMN_SOURCE=TAB_COLUMN_SOURCE||v_column_ora||'||'',''||' where table_name=c1.table_name;

--select count(*) into n_count from tab_column_ex where table_name=c1.table_name and tab_column=c1.column_name;

case when  c1.data_type='DATE' then

   select c1.column_name||' DATE "YYYY-MM-DD HH24:MI:SS"' into v_column_ora from dual;

   update tab_column_union set tab_column_ora=tab_column_ora||v_column_ora||','||chr(10) where table_name=c1.table_name;

when c1.data_type='NUMBER' then

   select c1.column_name||' INTEGER EXTERNAL' into v_column_ora from dual;

   update tab_column_union set tab_column_ora=tab_column_ora||v_column_ora||','||chr(10) where table_name=c1.table_name;

else


 update tab_column_union set tab_column_ora=tab_column_ora||c1.column_name||','||chr(10) where table_name=c1.table_name;


end case;


END LOOP;

--update tab_column_union t set tab_column_db2=substr(t.tab_column_db2,1,length(t.tab_column_db2)-1);

update tab_column_union t set tab_column_ora=substr(t.tab_column_ora,1,length(t.tab_column_ora)-2);

update tab_column_union t set TAB_COLUMN_SOURCE=substr(t.TAB_COLUMN_SOURCE,1,length(t.TAB_COLUMN_SOURCE)-7);

update tab_column_union t set TAB_COLUMN_SOURCE='select '||TAB_COLUMN_SOURCE||'from '||table_name||';';

    COMMIT;

end ETL_DOWNLOAD;

ci

步驟:1.先把須要從源庫導入到目標庫的表 在 目標庫中創建起來,表結構保持一致。文檔

         2.創建基礎表TAB_COLUMN_UNION

         插入須要生成控制文件的表名,注意表名要大寫,不然執行存儲過程會找不到表。

         3.創建存儲過程ETL_DOWNLOAD

執行存儲過程後會寫入TAB_COLUMN_ORA和TAB_COLUMN_SOURCE

再在sqlplus 下執行:

set lines 1000

set pages 0

select ctl_name from (
select 'spool /home/oracle/'||lower(table_name)||'.ctl' ctl_name,table_name, 0 cid from user_tables a where a.TABLE_NAME in (select table_name from tab_column_union)
union all
select 'select ''LOAD DATA',table_name,0.1 cid from user_tables a where a.TABLE_NAME in (select table_name from tab_column_union)
union all
select 'INFILE  ''''$ZM_PATH/'||table_name||'_$rq.CSV''''',table_name,0.11 cid from user_tables a where a.TABLE_NAME in (select table_name from tab_column_union)
union all
select 'TRUNCATE into table '||table_name,table_name,0.12 cid from user_tables a where a.TABLE_NAME in (select table_name from tab_column_union)
union all
select 'FIELDS TERMINATED BY  '||''''||''''||','||''''||''''||' OPTIONALLY ENCLOSED BY '||''''||''''||'"'||''''||'''',table_name, 0.2 cid from user_tables a where a.TABLE_NAME in (select table_name from tab_column_union)
union all
select 'TRAILING NULLCOLS',table_name,0.3 cid from user_tables a where a.TABLE_NAME in (select table_name from tab_column_union)
union all
select '(' ,table_name,0.4 cid from user_tables a where a.TABLE_NAME in (select table_name from tab_column_union)
union all
select b.tab_column_ora,a.table_name,0.5 cid from user_tables a ,tab_column_union b where a.table_name=b.TABLE_NAME
union all
select ') '' from dual;' ,table_name,0.6 cid from user_tables a where a.TABLE_NAME in (select table_name from tab_column_union)
union all
select 'spool off',table_name,0.7 cid from user_tables a where a.TABLE_NAME in (select table_name from tab_column_union)
) aa order by table_name,cid;

把執行結果複製出來寫入到一個文件裏,文件名ctlout1.sql

經過linux命令

sed  '/^$/d' ctlout1.sql> ctlout2.sql

去掉ctlout1.sql中的空行。

而後在經過sqlplus鏈接上目標庫,

先執行:

set lines 1000
set pages 0
set echo off
set feedback off
set heading off
set termout off
set trims on

而後再

@ctlout2.sql,會在/home/oracle下生成控制文件。

 

另外若是源庫也是oracle,那麼能夠在sqlplus下執行下列語句生成導出文件。

----生成導出文件

sqlplus  -s 下執行

set lines 1000
set pages 0
set echo off
set feedback off
set heading off
set termout off
set trims on

spool /home/oracle/dataout.sql
select txt_name from (
select 'spool /datafile/zmcf/ZMCF_CSV/'||upper(table_name)||'.CSV' txt_name,table_name, 0 cid from user_tables a where a.TABLE_NAME in (select table_name from tab_column_union)
union all
select t.tab_column_source,t.table_name,0.1 from tab_column_union t
union all
select 'spool off',table_name,0.7 cid from user_tables a where a.TABLE_NAME in (select table_name from tab_column_union)
) aa order by table_name,cid;

spool off

鏈接到源庫,

set lines 1000
set pages 0
set echo off
set feedback off
set heading off
set termout off
set trims on

@dataout.sql

生成數據文件,

須要先創建目錄:/datafile/zmcf/ZMCF_CSV

 

另外在個人環境源庫字符集gbk,目標庫字符集utf8

導出的時候設置export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

導出txt文件再導入到目標庫,

一樣在導入時先設置字符集

export NLS_LANG=AMERICAN_AMERICA.AL32UTF8

發現導入時老是報分隔符不正確,懷疑是字符集問題。

file -i 查看導出文件的字符編碼,發現內含中文的文件字符集並非gbk,而是其餘的字符集,可能問題就出如今這裏。

那麼就換種思路,再導出時,設置客戶端字符集爲:

export NLS_LANG=AMERICAN_AMERICA.AL32UTF8

而後再導出,查看導出文件,含中文的文件字符集已是utf-8

再把文件正常導入到目標庫,發現導入正常。

問題解決

相關文章
相關標籤/搜索