pg_trigger_depth()是否可用于防止触发级联(递归)?


8

为什么pg_trigger_depth() = 0在防止触发级联(递归)时不好用(除调试外)?

有人可以提供代码来证明它为什么不好吗?

我正在猜测,因为如果多个触发器同时在同一数据上运行,则使用触发器停止的条件pg_trigger_depth() = 0将停止第二行执行的任何触发器。

我认为这将是解决这个问题的好方法,但有人告诉我:

认为这将是一个很好的问题。

它在这里提供作为解决方案:

Postgres 9.3文档:

https://www.postgresql.org/docs/9.3/static/functions-info.html

Answers:


1

是的,让行为依赖于他人总是不好的 pg_trigger_depth()

也许我不太喜欢笼统的声明,但是这样做有什么好处呢?对于为什么要使用此功能,我没有任何争论。数据库的主要目的是确保数据完整性。而据我所看到的,我可能是错的,这样的使用始终 是一个潜在的违反的数据完整性。在@Erwin的回答中,他说“如果您忘记了”。确保完整性的目的是消除这种可能性。如果代理可以记住所有内容并了解其后果和周围的代码,则可以从任何事情中获得数据完整性。

让我们介绍一些术语,在编程中,我们有

  • “状态”,它包括程序员可以访问的任何内容
  • “执行上下文”,其中包括执行环境。

我们进一步有一个函数的术语,它没有状态称为 纯函数

给定相同的参数值,该函数始终求值相同的结果值。函数结果值不能取决于在程序执行过程中或在程序的不同执行之间可能改变的任何隐藏信息或状态,也不能取决于I / O设备的任何外部输入(通常-参见下文)。

因为它消除了任何负担,记得代计算机,或程序员的任何纯度的区别是有用的:f(x) = y永远正确的。在这里,您在最坏的地方违背了纯洁—数据库。而且,您以一种复杂且容易出错的方式进行操作-使内部执行上下文成为数据库应用程序状态中显而易见的事情。

我不会的 仅考虑您必须在精神上缓冲的复杂性。

  • Table ATrigger A大火
    • Trigger A总是向DML发出Table B,触发Trigger B
      • Trigger B有条件地向DML Table A发火Trigger A
      • Trigger B总是向DML发出Table A,触发Trigger A
    • Trigger A有条件地向DML Table B发火Trigger B
      • Trigger B有条件地向DML Table A发火Trigger A
      • Trigger B总是向DML发出Table A,触发Trigger A

如果看起来很复杂,请记住,可以“有条件地”将其进一步扩展为“它发生了,但是可能并不总是发生”“它没有发生,但是可能在其他地方发生”。

为了pg_trigger_depth()变得有用,您必须拥有一系列同样复杂的事件。而且,现在,您希望执行依赖于该链中的执行内容吗?

我会避免这种情况。如果您的触发系统是如此复​​杂,那么您就是一个人在壁橱里用手榴弹炸薯条,似乎收效不大。


10

这是不是不好用本身(恕我直言)您只需要注意含义即可。

我宁愿pg_trigger_depth() < 1代替pg_trigger_depth() = 0原则上的,但在此并不重要。我们谈论的是触发器,例如:

CREATE TRIGGER my_trigger
AFTER INSERT ON my_tbl
FOR EACH ROW
WHEN (pg_trigger_depth() < 1)
EXECUTE PROCEDURE my_trigger_func();

如果您以后添加了可以触发您的触发器的触发器,那么什么也不会发生。您的触发器仅对非触发事件做出反应。根据您的设置,这可能恰好是您想要的-或某种陷阱,如果您忘记了这一点,后来又添加了更多触发器,这些触发器又应(也)触发该触发器。您正在更改默认行为。确保清楚地记录下来。

请注意,除了触发相同的触发器以防止递归之外,它还pg_trigger_depth()任何触发器进行计数,因此如果从其他任何触发器调用该条件,也将阻止触发该触发器。
手册:

PostgreSQL触发器的当前嵌套级别(如果未从触发器内部直接或间接调用,则为0)

有关:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.