【问题标题】:Trigger calling stored procedure in Oracle在Oracle中触发调用存储过程
【发布时间】:2021-11-02 07:56:07
【问题描述】:

我有一个触发器,它调用存储过程(在表上插入之后)来执行许多 DML 语句。我的存储过程有一个提交,所以我的触发器失败了。经过一番研究,我在触发器中添加了 pragma automatic_transaction,现在它没有抱怨了。但我不确定这将如何影响我的触发器的行为。这是正确的方法还是只是让它工作的“黑客”?

这是我正在尝试做的伪代码

proc1 (input) - program logic then insert into table X, commit.

proc2 (input) - program logic then insert into table Y, commit.


trigger on table A AFTER INSERT
declare pragma autonomous_transaction

if :new value = 1 then
  proc1 (:new value)
else
  proc2 (:new value)
end if

【问题讨论】:

  • 请发布整个代码。
  • 您可能不应该在触发器的上下文中明确地commit,以允许包含事务控制行为,或者继续使用autonomous 行为。以下内容可能有助于确定您可能需要哪种方法:docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/… ... 请记住,自主行为可能会导致它与包含事务之间的死锁。
  • 你需要检查自治事务的机制in the docs并决定。

标签: sql oracle triggers


【解决方案1】:

让我们考虑一下程序流程:

  • 您开始交易。
  • 您对表执行 DML 操作。
  • 您的触发器触发并且是一个自治事务,因此创建一个单独的事务。
  • 您的原始交易继续进行。
  • 也许您在该原始交易中执行了其他 DML 操作。
  • 其中一个额外的 DML 操作会引发异常。
  • 回滚您的整个事务(但不是单独的自治事务)。

但是:

  • 您启动了一个单独的自治事务。
  • 调用存储过程。
  • 其中有许多 DML 语句。
  • 然后触发器提交它们。

您处于有两个事务的状态,原始事务已回滚并且自治事务已提交。


如果自治事务用于记录,并且您希望它始终记录原始事务失败或成功的操作,那么这种行为很好。

如果自治事务是正常业务逻辑的一部分,那么您可能会处于不一致状态,其中一半事务被回滚,一半被提交;这不是你想要的。

在后一种情况下,正常的解决方案是从触发器中删除 COMMIT 并使其成为非自治事务,然后由触发器产生的 DML 将成为原始事务的一部分并被提交(或回滚)该事务。


这是我正在尝试做的伪代码

proc1 (input) - program logic then insert into table X, commit.
proc2 (input) - program logic then insert into table Y, commit.

见:What is the effect of placing the commit after DML in procedure?

一般来说,您应该在过程中添加COMMIT,因此您的伪代码应该是:

proc1 (input) - program logic then insert into table X.
proc2 (input) - program logic then insert into table Y.

你的触发器不应该是一个自治事务。

那么你的程序流程是:

  1. 插入表A
  2. 触发火灾
  3. 根据价值,请致电proc1proc2
  4. 完成程序。
  5. 完成触发器。
  6. 完成交易并COMMIT(来自执行插入的代码或在交易关闭时自动完成)。

【讨论】:

  • 说明触发器是否在插入后位于表 A 上。并且触发器设置为自主事务。触发器中的代码没有 DML,只有一大堆 If 语句,它执行 DML 的唯一时间是它调用一个将记录插入表 B 的存储过程。如果我理解正确,你是说如果插入到表 A 中回滚,表 B 中的记录仍然存在吗?但是触发器是在插入表 A 之后,如果插入错误,触发器不会首先触发吗?
  • @Tommy 我的意思是,如果触发器和它调用的 DML 是与原始 DML 相同的一组操作的一部分,那么它应该是同一事务的一部分并且不要使用一个自治事务。如果触发器和它调用的 DML 独立于原始 DML(即,如果您正在记录一个动作,而不管该动作是成功还是失败),那么它应该是一个自治事务。确定您是否需要一两笔交易,然后将其转化为解决方案,而不是在可能不需要时尝试将COMMIT 破解到语句中。
  • 谢谢,问题是 proc 是我无法更改的,它不属于我,我无法编辑它。我无法编辑提交。我可能不得不编写自己的版本,这很糟糕,因为如果那个版本改变了,我的也需要改变。
猜你喜欢
  • 2011-09-30
  • 1970-01-01
  • 1970-01-01
  • 2013-12-30
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多