sqlldr批量生成控制文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sqlldr批量生成控制文件相关的知识,希望对你有一定的参考价值。

参考文档:http://askjoey.blog.51cto.com/7594056/1671852

环境:oracle11g,redhat linux

1.建立基础表

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
  );

table_name 中插入需要生成控制文件的表名。

TAB_COLUMN_ORA 通过存储过程生成表对应的每列

TAB_COLUMN_SOURCE 通过存储过程生成导出成数据文件的语句,这里假设源库和目标库都是oracle

存储过程如下:

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;

步骤: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

再把文件正常导入到目标库,发现导入正常。

问题解决

 

以上是关于sqlldr批量生成控制文件的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 批量插入数据怎么做

用SQLLDR来装载date类型的控制文件

SQLLDR用武之地

oracle sqlldr 参数说明

批量数据文件用sqlldr导数据到oracle中

批量数据文件用sqlldr导数据到oracle中