mou*_*r11 9 postgresql trigger
为什么pg_trigger_depth() = 0在防止触发器级联(递归)时使用(除调试之外的)不好?
有人可以提供代码来证明它为什么不好吗?
我猜测是因为如果多个触发器同时处理相同的数据,则停止使用触发器的条件pg_trigger_depth() = 0将停止任何排在第二位的触发器。
我认为这将是解决这个(我的)问题的好方法,但有人告诉我:
认为这会是一个很好的问题。
它在此处作为解决方案提供:
Postgres 9.3 文档:
https://www.postgresql.org/docs/9.3/static/functions-info.html
Erw*_*ter 12
这是不是不好用本身(恕我直言)你只需要意识到影响。
我宁愿让它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();
Run Code Online (Sandbox Code Playgroud)
如果您稍后添加会依次触发您的触发器的触发器,则不会发生任何事情。您的触发器仅对非触发器事件作出反应。根据您的设置,这可能正是您想要的 - 或者是一种陷阱,如果您忘记了这一点,然后添加更多触发器,这些触发器应该反过来(也)触发此触发器。您正在更改默认行为。一定要清楚地记录这一点。
请注意,pg_trigger_depth()计数任何触发器,不仅是防止递归的同一个触发器,因此如果从任何其他触发器调用,条件也会阻止触发器触发。
手册:
PostgreSQL 触发器的当前嵌套级别(如果没有直接或间接从触发器内部调用,则为 0)
有关的:
pg_trigger_depth()也许我不太反对笼统的陈述,但这有什么好处呢?我认为没有任何理由可以解释您为什么需要这样的功能。数据库的主要目的是确保数据完整性。据我所知,我可能是错的,这种使用总是 潜在地违反数据完整性。在@Erwin 的回答中,他说“如果你忘记了”。确保完整性的目的是消除这种可能性。如果代理可以记住所有内容并理解其后果和代码,那么您就可以从任何内容中获得数据完整性。
\n\n让我们介绍几个术语,在编程中,我们有
\n\n我们还有一个函数术语,它没有状态,我们称之为 纯函数,
\n\n\n\n\n给定相同的参数值,该函数始终计算相同的结果值。函数结果值不能依赖于程序执行过程中或程序不同执行之间可能改变的任何隐藏信息或状态,也不能依赖于来自 I/O 设备的任何外部输入(通常\xe2\x80\x94,见下文) 。
\n
纯度的区别是有用的,因为它消除了代表计算机或程序员记住任何内容的任何负担:始终f(x) = y如此。在这里,你在最糟糕的地方——数据库——违反了纯度。而且,您正在以一种复杂且容易出错的方式执行此操作 - 使内部执行上下文在数据库应用程序的状态中变得显而易见。
我不想那样。只需考虑一下您必须在心理上缓冲的复杂性即可。
\n\nTable A\Trigger A着火\n\nTrigger A始终向 发出 DML Table B,并触发Trigger B。\n\nTrigger B有条件地发出 DML 到Table A,触发Trigger A。Trigger B总是发出 DML 来Table A触发Trigger A。Trigger A有条件地向 发出 DML Table B,触发Trigger B。\n\nTrigger B有条件地发出 DML 到Table A,触发Trigger A。Trigger B总是发出 DML 来Table A触发Trigger A。如果这看起来很复杂,请记住“有条件地”可以进一步扩展到“它发生了,但它可能并不总是发生”和“它没有发生,但它可能在其他地方发生”。
\n\n为了pg_trigger_depth()变得有用,你必须有一系列同样复杂的事件。现在,您希望执行依赖于该链中的执行内容吗?
我会避免这种情况。如果你的触发系统如此复杂,那么你就只能独自在壁橱里用手榴弹玩烫手山芋,而且结局似乎不太可能好。
\n