1

我在表 A 上有一个更新后触发器(触发器 A),它可以对表 B 进行更改。

我在表 B 上还有一个更新后触发器(触发器 B),它没有进行任何更改,但查询表 A 以对非规范化进行一些健全性检查。

所以触发器 B 可以触发以下两种方式之一:

  1. 如果我直接更新表 B,或者
  2. 如果我更新表 A 并且触发器 A 触发,导致表 B 更新。

在案例 2 中,我得到一个 ORA-04091: table name is mutating, trigger/function may not see it error。这似乎是正确的。

我想在触发器 B 中检查表 A 是否“处于错误状态”并提前退出(在这种情况下不需要运行健全性检查)。

在我的触发器中测试它的最佳方法是什么?只需添加一个吞下异常的异常处理程序?还有比这更优雅的吗?

4

1 回答 1

2

您可以让 A 上的触发器做一些事情来提醒 B 上的触发器它不需要触发。有各种希望为会话设置某种状态。最简单的可能方法是创建一个带有布尔变量的包,bypass_checks_on_b在执行ATRUE之前设置为,一旦完成,然后在 B 上的触发器中检查此变量的状态,然后再执行验证。您也可以对临时表或上下文执行类似的操作,而不是使用包。效率较低,您可能会解析 B 上的触发器内的调用堆栈,以查看 A 上的触发器是否在调用堆栈中,但这往往会相当难看。UPDATEFALSEUPDATE

不过,我会对整个架构非常谨慎。当您发现 A 上的触发器导致 B 上的触发器触发想要查询 A 时,几乎总是这样的情况是您在触发器中放置了太多逻辑并且您会更好地移动将该逻辑放入可以调用的存储过程层,而不是应用程序执行直接插入或更新。当您将太多逻辑推入触发器时,您最终会得到一个非常难以理解的系统,因为从应用程序代码中看各种语句具有什么样的副作用并不明显。你最终会得到非常有状态的代码,根据调用者的不同,你有许多通过单个代码的路径。这几乎可以肯定意味着会有一些州你不测试或不测试' 不要想你会在哪里发现你的代码做了一些意想不到的事情。在拥有大量状态和拥有大量副作用的代码库之间,您可以非常快速地构建一个本质上不可维护的代码库。

于 2012-04-13T16:09:58.410 回答