0

以下のようにトリガー TEST_TRIG を作成しました。

CREATE TRIGGER TEST_TRIG
   AFTER INSERT ON TEST_TABLE
   FOR EACH ROW
 DECLARE
   PRAGMA AUTONOMOUS_TRANSACTION;
 BEGIN
   TEST_PROC();
 END;

プロシージャ TEST_PROC コード:

create or replace
PROCEDURE TEST_PROC 
AS
BEGIN
EXECUTE IMMEDIATE 'truncate table TEST_FINAL';
  INSERT INTO TEST_FINAL select * from TEST_TABLE;
  commit;
END;

最初に、TRIGGER TEST_TRIG を無効にして、TEST_TABLE にレコードを挿入し、PROCEDURE TEST_PROC を手動で実行しました。

出力: TEST_FINAL から TEST_TABLE に挿入したものと同じレコードを取得できました。


これらのレコードを両方のテーブルからフラッシュし、トリガー TEST_TRIG を有効にしました。

TEST_TABLEにレコードを挿入してコミットすると、TEST_FINALテーブルにレコードが見つかりませんでした...エラーメッセージも表示されません!!!

トリガーが発射されたかどうかを知りたいですか?

4

1 に答える 1

1

AUTONOMOUS_TRANSACTION の意味を完全に把握しているとは思いません。事実上、プラグマによって制限されたコードが別のセッションで実行されることを意味します。そのため、Oracle の読み取り整合性分離レベルにより、自律型トランザクションは、メイン トランザクションによって生成されたデータ変更を認識できません。

したがって、トリガーを開始したときに TEST_TABLE が空の場合、現在挿入している行数に関係なく、TEST_FINAL に 行は挿入されません。

したがって、両方のテーブルをフラッシュしないでください。TEST_TABLE にいくつかの行を挿入してコミットします。TEST_FINAL はまだ空です。さらにいくつかの行を TEST_TABLE に挿入してください。行の最初のセットは TEST_FINAL に表示されます。

明らかに、これはあなたが望む結果ではありません。したがって、ロジックを再検討する必要があります。毎回 TEST_FINAL を切り捨てることは本当に意味がありません。また、FOR EACH ROW を切り捨てることは絶対に意味がありません。それがサックです!パフォーマンスに関する限り。同様に、同じ理由で、ターゲット テーブルに INSERT ... SELECT を入力しても意味がありません。

TRUNCATE を破棄すると、プラグマが不要になり、すべてがはるかに簡単になります。

影響を受けた行の履歴を保持したい場合は、代わりに次のようなものを使用してください。

CREATE TRIGGER TEST_TRIG
   AFTER INSERT ON TEST_TABLE
   FOR EACH ROW
BEGIN
    insert into test_final (col1, col2)
    values (:new.col1, :new.col2);
END;

正確な要件に合わせて正確なコードを変更する必要があります。

于 2013-06-04T14:34:27.140 に答える