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 的含义。实际上,这意味着受 pragma 限制的代码在单独的会话中运行。所以,由于Oracle的读一致性隔离级别,自治事务看不到主事务产生的任何数据变化。

因此,如果在您启动触发器时 TEST_TABLE 为空,则无论您现在插入多少行,触发器都不会在 TEST_FINAL 中 插入任何行。

所以:不要刷新两个表。将一些行插入 TEST_TABLE 并提交。TEST_FINAL 仍将为空。在 TEST_TABLE 中插入更多行,瞧!第一组行将出现在 TEST_FINAL 中。

显然这不是你想要的结果。所以你需要重新审视你的逻辑。每次都截断 TEST_FINAL 确实没有意义,而且绝对不是 FOR EACH ROW。那是德吸!就性能而言。同样,出于同样的原因,用 INSERT ... SELECT 填充目标表没有意义。

丢弃 TRUNCATE 意味着您不需要 pragma 并且一切都变得更加简单,

如果您想保留受影响行的历史记录,请改用以下内容:

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 回答