2

下記にご協力をお願いいたします。2 つの行を持つテーブルがあり、1 つの行を削除しているときにトリガーを書き込み、削除後に残る他の行のステージング テーブル (staging_tbl) にレコードを書き込みたいと考えています。ただし、有効な変化トリガーエラーがスローされます。しかし、それを回避してレコードをステージングテーブルに書き込む方法はありますか?メインテーブルに2行あり、そのうちの1行が削除されます(テーブルのすべての削除ではありません)。

create or replace TRIGGER a_del_trg
  after delete on item_master
  for each row

DECLARE

  l_item NUMBER :=0;
  l_item_parent number :=0;
BEGIN

  INSERT INTO tmp_chk (item,item_parent) VALUES (:OLD.item,:OLD.item_parent);

  SELECT a.item,a.item_parent INTO l_item , l_item_parent
  FROM item_master a , tmp_chk  b  WHERE  a.item_parent = b.item_parent
  and a.item != b.item;

      INSERT INTO staging_tbl
        (create_date, table_name, item_sku, if_name)
      values
        (SYSDATE, 'Item_master', l_item, 'W'); -- want to add the remaining item here
    END IF;

END a_del_trg;
4

1 に答える 1

1

プラグマ AUTONOMOUS_TRANSACTION

次のステートメントを使用してエラーを再現しました。

create table item_master(item number, item_parent number);
insert into item_master values (1, 10);
insert into item_master values (2, 10);

create table tmp_chk(item number, item_parent number);

create table staging_tbl(create_date date, table_name varchar2(30), item_sku number, if_name varchar2(10));

私はあなたのトリガーを使用しました(トリガーEND IFの最後から残留コードを削除した後)。エラーが発生しました"ORA-04091: table name is mutating, trigger/function may not see it." message.

この適切な説明を参照するFix Oracle mutating trigger table errors、次の抜粋を繰り返す必要があります。

結局のところ、変更テーブル エラーは通常、アプリケーションの設計が不十分な結果であり、変更トリガーは可能な限り回避する必要があります。

リファレンスの 4 番目のオプションに従って、autonomous transactionsトリガーを次のように書き直しました。

create or replace TRIGGER a_del_trg
  after delete on item_master
  for each row

DECLARE

  l_item NUMBER :=0;
  l_item_parent number :=0;
  pragma autonomous_transaction;
BEGIN

  INSERT INTO tmp_chk (item,item_parent) VALUES (:OLD.item,:OLD.item_parent);
  
  SELECT a.item,a.item_parent INTO l_item , l_item_parent
  FROM item_master a , tmp_chk  b  WHERE  a.item_parent = b.item_parent
  and a.item != b.item;

      INSERT INTO staging_tbl
        (create_date, table_name, item_sku, if_name)
      values
        (SYSDATE, 'Item_master', l_item, 'W'); -- want to add the remaining item here
commit;
END a_del_trg;
/

クエリの実行:

select * from item_master;
2   10

select * from tmp_chk ;
1   10

select * from staging_tbl;
27-NOV-15   Item_master 2   W

ロールバック

ここから:

「... 1000 回中 999 回、自律型トランザクションの使用を「強制」されていることに気付いた場合、それはおそらく、考えもしなかった深刻なデータ整合性の問題があることを意味します。

人々はどこでそれらを使用しようとしますか?

  • (エラー ログ ルーチンではなく) コミットするプロシージャを呼び出すトリガー内。ああ、ロールバックすると痛いはずです。
  • 可変テーブル制約を取得しているそのトリガーで。痛い、それはさらに痛い
  • エラー ログ - OK。
  • 他のほとんどすべて - OK ではありません。」
于 2015-11-27T07:03:20.367 に答える