我在表 A 上有一个更新后触发器(触发器 A),可以对表 B 进行更改。
我在表 B 上还有一个更新后触发器(触发器 B),它不进行任何更改,但查询表 A 以对非规范化进行一些健全性检查。
因此触发器 B 可以通过以下两种方式之一触发:
- 如果我直接更新表 B,或者
- 如果我更新表 A 和触发器
A 触发,导致表 B 更新。
在情况 2 中,我收到 ORA-04091: table name is mutating, trigger/function may not see it 错误。这似乎是正确的。
我想在触发器 B 中检查表 A 是否“处于不良状态”并提前退出(在这种情况下不需要运行健全性检查)。
在我的触发器中测试此功能的最佳方法是什么?只需添加一个吞掉异常的异常处理程序?还有比这更优雅的事吗?
您可以让 A 上的触发器执行某些操作来提醒 B 上的触发器不需要触发。有多种想要为会话设置某种状态的想法。最简单的方法是创建一个带有布尔变量的包bypass_checks_on_b
你设置为TRUE
在你做之前UPDATE
在 A 上,设置为FALSE
一旦UPDATE
完成,然后在进行验证之前检查 B 上触发器中该变量的状态。您也可以使用临时表或上下文执行类似的操作,而不是使用包。效率较低,您可能会解析 B 上的触发器内的调用堆栈,以查看 A 上的触发器是否在调用堆栈中,但这往往相当难看。
不过,我对整个架构非常谨慎。当您发现 A 上的触发器导致 B 上的触发器想要查询 A 时,几乎总是这样,您在触发器中放置了太多逻辑,并且移动会更好将该逻辑放入可以调用的存储过程层中,而不是应用程序进行直接插入或更新。当您将太多逻辑放入触发器中时,您最终会得到一个非常难以理解的系统,因为通过查看应用程序代码,各种语句具有哪些副作用并不明显。最终你会得到非常有状态的代码,其中根据调用者的不同,一段代码有很多路径。这几乎肯定意味着有些状态您没有测试或没有想到您会发现您的代码做了一些意想不到的事情。在拥有大量状态和具有大量副作用的代码库之间,您很快就可以构建本质上无法维护的代码库。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)