【发布时间】:2021-12-02 03:05:49
【问题描述】:
我想使用触发器审核 PostgreSQL 表中的 created_by、created_timestamp、modified_by 和 modified_timestamp 列。创建 BEFORE INSERT 和 BEFORE UPDATE 触发器以将这些值设置为 current_user 和 now() 相当简单。
但是,如果有人尝试这样做:
INSERT INTO SOMETABLE(someColumn, created_by) VALUES ('test', 'someOtherUser');
我宁愿抛出一个异常,例如“不允许在 INSERT 查询中手动设置 created_by。”而不是让触发器静默地将 'someOtherUser' 更改为 current_user。
我认为我可以通过以下方式在触发器中完成此操作:
if new.created_by is not null then raise exception 'Manually setting created_by in an INSERT query is not allowed.'; end if;
这对 INSERT 查询和触发器按预期工作。
但是,对于 UPDATE 触发器使用相同的策略,我发现它有点困难,因为除了 UPDATE 查询中的更改值之外,NEW 记录还具有来自现有行的未更改值。 (至少,我认为这是正在发生的事情。)
我可以比较 new.created_by 和 old.created_by 以确保它们相同,从而防止查询更改值,但即使最终结果相似(即表中的值没有改变),这实际上与根本不允许该列出现在 UPDATE 查询中是不一样的。
是否有一种优雅的方法可以确定 INSERT 或 UPDATE 查询中是否存在列?我在这里看到了一些转换为 JSON 并以这种方式进行测试的建议,但这对我来说似乎是一个相当丑陋的解决方案。
是否有其他解决方案来确保这些列(created_by、created_timestamp 等)仅由触发器函数设置,而不能在 INSERT 和 UPDATE 查询中手动设置?
【问题讨论】:
-
Postgres 中的
UPDATE是DELETE(OLD) 记录和INSERT(NEW) 记录操作。这意味着所有列都将出现在每条记录中。如果您在触发器中将created_by设置为current_user之前进行测试,不知道为什么如果它们不相同则不能抛出异常?
标签: postgresql postgresql-triggers