あなたはすでに解決策の途中です:
これは驚きではありません。現在の実装では、テーブルBに挿入する行ごとに多数の単一行SELECTステートメントが実行されます。これにより、必然的にパフォーマンスプロファイルが低下します。 SQLはセットベースの言語であり、複数行の操作でパフォーマンスが向上します。
したがって、あなたがする必要があるのは、より効率的な代替手段であるすべてのSELECTステートメントを置き換える方法を見つけることです。その後、トリガーを永続的にドロップできるようになります。たとえば、ディクショナリのルックアップを、テーブルAの列と参照テーブルの間の外部キーに置き換えます。 Oracleの内部コードであるリレーショナル整合性制約は、私たちが記述できるどのコードよりもはるかに優れたパフォーマンスを発揮します(マルチユーザー環境でも機能します)。
列の組み合わせがテーブルBにすでに存在する場合、テーブルAに挿入しないという規則は、より問題があります。難しいからではなく、リレーショナルデザインが貧弱に聞こえるからです。レコードがすでにテーブルBに存在しているときに、テーブルAにレコードをロードしたくない場合は、テーブルBに直接ロードしないのはなぜですか。または、テーブルAおよびから抽出する必要がある列のサブセットがある場合もあります。 テーブルBとテーブルC(AおよびBとの外部キー関係を持つ)に形成されますか?
とにかく、それを一方に任せて、SQL * Loaderを外部テーブルに置き換えることにより、セットベースのSQLでこれを行うことができます。外部テーブルを使用すると、CSVファイルを通常のテーブルであるかのようにデータベースに表示できます。これは、通常のSQLステートメントで使用できることを意味します。 詳細a>
したがって、ディクショナリと外部テーブルに対する外部キー制約を使用すると、SQLローダーコードをこのステートメントに置き換えることができます(「...など」に含まれる他のルールに従う必要があります):
insert into table_a
select ext.*
from external_table ext
left outer join table_b b
on (ext.name = b.name and ext.last_name = b.last_name and ext.dept=b.dept)
where b.name is null
log errors into err_table_a ('load_fail') ;
これは、DMLエラーロギング構文を使用して、セットベースの方法ですべての行の制約エラーをキャプチャします。 詳細a> 。テーブルBにすでに存在する行の例外は発生しません。
おそらくあなたが予想していたよりも複雑な答えです。 Oracle SQLは非常に広範なSQL実装であり、一括操作の効率を向上させるための多くの機能を備えています。コンセプトガイドとSQLリファレンスを読んで、Oracleでどれだけのことができるかを知ることは本当に私たちに報われます。