【发布时间】:2020-09-09 15:53:34
【问题描述】:
我在 PostgreSQL 中研究一组触发器,我想我偶然发现了内置函数/触发器 suppress_redundant_updates_trigger() 上的一个错误。它在我的配置(我的笔记本电脑上的 PostgreSQL 12)上完全可以重现。
首先我建立了一个表格,有两个“每行之前”触发器:
CREATE TABLE test (id int, val text);
INSERT INTO test VALUES (1, 'one'), (2, 'two');
CREATE OR REPLACE FUNCTION am_i_touched() RETURNS trigger LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
RAISE NOTICE 'Yes, I am touched!';
RETURN NEW;
END;
$BODY$;
CREATE TRIGGER az_test_suppress_redundant_update
BEFORE UPDATE ON public.test
FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
-- Make sure trigger name is after the previous one
-- in alphabetical order as it drives execution order
CREATE TRIGGER bz_am_I_touched
BEFORE UPDATE ON public.test
FOR EACH ROW EXECUTE PROCEDURE am_i_touched();
然后我运行UPDATE test SET id = 1 WHERE id = 1。正如预期的那样,更新被第一个触发器抑制,因为该行保持不变,并且bz_am_i_touched() 永远不会触发。到目前为止一切顺利。
然后我跑了:
ALTER TABLE test ADD COLUMN newcol int
现在,我再次运行UPDATE test SET id = 1 WHERE id = 1...这一次,更新没有被禁止,bz_am_i_touched() 触发! PGAdmin (v4) 报告更新了一条记录,而不是像以前那样为零!
这是一次性事件。进一步UPDATE test SET id = 1 WHERE id = 1 按预期工作...但后来我尝试UPDATE test SET id = 2 WHERE id = 2...又出现了这种奇怪的行为 - 更新没有被禁止。
这是预期的行为吗?我不明白UPDATE test SET id = 1 WHERE id = 1 是如何导致更新不被禁止的。
【问题讨论】:
-
听起来很可疑。您应该将其作为错误报告给 PostgreSQL。
-
是的,我现在正在这样做......这并不像看起来那么牵强,因为许多与审计相关的设置都在精确地向表中添加列以及定义触发器。 ..这就是我正在做的事情。
标签: postgresql triggers postgresql-12