2012-05-10 22 views
2

データベースリンク上で使用すると、Oracle上でのforall .. insertの使用を禁止する実装制限があるように見えます。非常にが紛らわしい、これが次のエラーで9iのに失敗し データベースリンクを介したバルク挿入の制限の克服

connect schema/[email protected] 

create table tmp_ben_test (
    a number 
, b number 
, c date 
, constraint pk_tmp_ben_test primary key (a, b) 
    ); 

Table created. 

connect schema/[email protected] 
Connected. 

declare 

    type r_test is record (a number, b number, c date); 
    type t__test is table of r_test index by binary_integer; 
    t_test t__test; 

    cursor c_test is 
    select 1, level, sysdate 
     from dual 
    connect by level <= 10 
      ; 

begin 

    open c_test; 
    fetch c_test bulk collect into t_test; 

    forall i in t_test.first .. t_test.last 
    insert into [email protected] 
    values t_test(i) 
      ; 

    close c_test; 

end; 
/

ERROR at line 1: ORA-01400: cannot insert NULL into ("SCHEMA"."TMP_BEN_TEST"."A") ORA-02063: preceding line from DB1 ORA-06512: at line 18

た場合のみ11グラムでチェックした後、私が実現した、これは実装上の制約だったこれは、実証する簡単な例であります。

ERROR at line 18: ORA-06550: line 18, column 4: PLS-00739: FORALL INSERT/UPDATE/DELETE not supported on remote tables

このラウンドは本当に明白な方法はにforall ..を変更することです:

for i in t_test.first .. t_test.last loop 
    insert into [email protected] 
    values t_test(i); 
end loop; 

が、すべての可能性であれば、私はむしろ、単一のインサートにそれを維持したいです。 Tom Kyte suggests the use of a global temporary table。 GTTにデータを挿入した後、DBリンクを介してデータを挿入すると、既にユーザー定義型のデータセットに対する大過剰なオーバーヒルのように思えます。

この例を明確にすると、実際に起こっていることと比べて、極端にはです。 insert intoを簡単に実行できる方法はなく、すべての操作をGTTで実行する方法はありません。コードの大部分はユーザー定義型で行う必要があります。

この制限を回避する別のDMLyがありますか?

+0

あなたはGTT ideeaを試しましたか? 11gの性能を比較してください。私は過労ではないが、日付を移動するための迅速な方法だと思う。 –

+0

いいえ私はそれを試していない。私は明らかに他の選択肢がないかどうかはわかります。メモリから何かを取るのはちょっと変わったようです。別のメモリに移動してDMLを実行します。よりシンプルなソリューションを望んでいました。存在する場合。 – Ben

+0

少し考えてみてください。 GTTの部分は純粋なSQLであり、速くなります(dblinkのペナルティ)。遅いのは、配列を持つps/sqlの部分です... –

答えて

2

リモートデータベースではどのような制限がありますか?そこにオブジェクトを作成できる場合、回避策があります。リモート・データベースで、コレクションのタイプと、そのコレクションをパラメーターとし、FORALLステートメントを実行するプロシージャーを作成します。

+0

私はどこにも制限がありません。これらはDBを処理するだけであり、外部の世界には接続していません。あなたが何を意味するかを見るのに数秒かかりました。パラメータとして型をとり、私のために挿入するdb2'からの 'db1'のプロシージャを実行しますか? – Ben

1

db2でt__test/r_test型を作成し、db1でパブリック・シノニムを作成すると、db1からdb2にt_tableを充填してdb1に戻るプロシージャを呼び出すことができます。次に、ローカルテーブルに挿入できるはずです。

実際には、無名ブロックではなく、パッケージ化されたタイプとプロシージャを使用することを前提としています。

また、大きなデータセットには理想的なソリューションではないため、GTTなどが優れています。

関連する問題