1

これがシナリオです。データベースに約 300 のテーブルがあり、データベースに別のデータベースをマージしたいと考えています。両方のデータベースに同じテーブルがありますが、データ型と列数が異なります。他のデータベースから私のデータベースにデータを変換する方法は?

例えば。

db1: テーブル T1(col1 int,col2 char,......,col31 int)
db2: テーブル T1(col1 int,col2 char,......,col31 int,col32 char,col33 char )

データ型と列の数が異なるため、「insert into db1.tbl select * from db2.tbl」は使用できません。

すべてのテーブルごとにスクリプトを作成したくありません。手伝ってください !!!

4

1 に答える 1

0

毎朝、本番データベースからデータウェアハウスに大量のテーブルをコピーします。これは、各切り捨て+挿入の前に実行する「チェック&フィックス」手順です。

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   user_tab_cols@DB_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';

お役に立てれば :)

于 2012-07-13T13:39:05.103 に答える