參考文檔: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
再把文件正常導入到目標庫,發現導入正常。
問題解決