每天早上我會將大量的表格從生產數據庫複製到我的數據倉庫中。這是我在每次截斷+插入之前運行的「檢查&修復」過程。
procedure check_and_fix_table(p_naam in varchar2)
/**
* check if columns have changed on PROD and create and execute the matching ALTER TABLE statement
*/
is
v_coltype varchar2(100);
v_sql varchar2(200);
function check_column(p_column in varchar2)
return boolean
is
v_dummy number;
begin
select 1 into v_dummy
from user_tab_cols tc
where tc.table_name = upper(p_naam)
and tc.column_name = p_column;
return true;
exception
when no_data_found then return false;
end;
begin
-- loop through all columns that are altered (if nothing altered, then nothing will happen
for i in (select tc.column_name
, tc.data_type
, tc.data_length
, tc.data_precision
from [email protected]_LINK_TO_PRODUCTION tc
where tc.table_name = upper(p_naam)
and tc.column_name not like 'SYS_NC%' -- These columns are created by oracle for function based indexes
minus
select tc.column_name
, tc.data_type
, tc.data_length
, tc.data_precision
from user_tab_cols tc
where tc.table_name = upper(p_naam))
loop
-- create column type
if i.data_type in ('CHAR','VARCHAR2') then
v_coltype := i.data_type||'('||i.data_length||')';
elsif i.data_type = 'NUMBER' then
if i.data_precision is not null then
v_coltype := i.data_type||'('||i.data_precision||')';
else
v_coltype := i.data_type;
end if;
else -- DATE, CLOB, BLOB, etc
v_coltype := i.data_type;
end if;
-- check if the column is altered or added
if check_column(i.column_name) then
-- execute the ALTER TABLE to fix the column
v_sql := 'alter table '||p_naam||' modify '||i.column_name||' '||v_coltype;
else
-- add new column
v_sql := 'alter table '||p_naam||' add '||i.column_name||' '||v_coltype;
end if;
execute immediate v_sql;
-- logging change
prc_log(c_procedureid, 1, p_naam||' changed. Fixed by executing: '||v_sql);
end loop;
exception
when others then
prc_log(c_procedureid, 3, 'Error at copy_package.check_and_fix_table - '||substr(sqlerrm, 0, 1900));
end;
然後在我的主過程我用它像這樣(其中p_naam作爲參數傳遞給該過程的表名):
check_and_fix_table(p_naam);
-- full copy of table from PROD
execute immediate 'truncate table ' || p_naam;
execute immediate 'insert /*+append*/ into ' || p_naam || ' select * from ' || p_naam || '@DB_LINK_TO_PRODUCTION';
希望這有助於:)
你能保證具有相同名稱的列是相同類型的? – martin 2012-07-13 11:27:32
你只想合併來自兩個數據庫的數據嗎? 如果是這樣,並且您碰巧擁有一個領先的數據庫(具有適當的列和類型的數據庫),您可以創建一個通用腳本。該腳本可以轉換類型,剝離不可用的列或爲以前不存在的列添加空值/默認值。 – Deruijter 2012-07-13 13:25:29
如果@ martin正確,並且您不能保證列具有相同的名稱或相同的順序,那麼您需要手動執行此操作。如果可以的話,你可以創建一個大量過度複雜的動態腳本。 – Ben 2012-07-14 09:11:09