PL/PGSQL触发器如何检测UPDATE上的SQL语句中是不是提供了列?
Posted
技术标签:
【中文标题】PL/PGSQL触发器如何检测UPDATE上的SQL语句中是不是提供了列?【英文标题】:PL/PGSQL trigger how to detect if a column is provided in the SQL statement on UPDATE?PL/PGSQL触发器如何检测UPDATE上的SQL语句中是否提供了列? 【发布时间】:2020-10-12 11:41:11 【问题描述】:我正在 Postgres 中编写一个 PLPGSQL 触发器,我想检测更新语句中是否提供了一个列。我有一个用户 ID,我想用它来跟踪更改。问题是,如果 user_id 已经在我要更新的记录中并且 UPDATE SQL 不提供 user_id,则使用旧的 user_id。我想检测请求是否没有在更新中提供 user_id 以引发异常。 这是否可以在触发器中实现,还是我需要确保始终在所有请求中添加 user_id?
例如,这应该抛出一个异常:
UPDATE table SET field1 = 'test' WHERE id=1
这应该完全运行触发器,因为用户 ID 在更新中:
UPDATE table SET field1 = 'test',user_id = 2 WHERE id=1
我正在实施审计并希望确保 user_id 始终是请求的一部分。
谢谢
【问题讨论】:
请发布您期望的示例输入和输出数据。 例如:这应该引发异常UPDATE table SET field1 = 'test' WHERE id=1
这应该完全运行触发器,因为用户 ID 在更新中 UPDATE table SET field1 = 'test'
,user_id = 2 WHERE id=1` 我正在实施审计和希望确保 user_id 始终是请求的一部分。
提供了user_id
但与现有相同的情况怎么办?问题是在 Postgres 中 UPDATE
是 DELETE
/INSERT
。这意味着在触发函数中,NEW
和OLD
'tables' 将包含所有列值。所以从它的角度来看,user_id
总是存在的。你能做的最好的就是看看它的价值是否改变了。有关更多信息,请参阅here。您可能想查看可用的用户信息 here 并映射到 user_id
。
【参考方案1】:
写两个AFTER UPDATE
触发器:
一个名为 trigger1
的 AFTER UPDATE OF (user_id)
触发器仅包含 RETURN NULL
一个名为trigger2
的AFTER UPDATE
触发器无条件抛出错误
然后触发器将按该顺序执行,因为trigger1
按字母顺序排列在trigger2
之前。
如果user_id
在SET
列表中,trigger1
将执行并终止处理,因为它返回 NULL,因此trigger2
不会运行并且不会引发错误。
如果user_id
不在SET
的欲望中,trigger1
将不会运行,trigger2
将抛出错误。
有关触发器执行顺序的说明,请参阅the documentation。
【讨论】:
非常聪明,我喜欢!虽然我建议在触发器执行的顺序上添加对documentation 的引用:“如果为同一关系上的同一事件定义了多个触发器,则触发器将按触发器名称的字母顺序触发。”以上是关于PL/PGSQL触发器如何检测UPDATE上的SQL语句中是不是提供了列?的主要内容,如果未能解决你的问题,请参考以下文章