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 中 UPDATEDELETE/INSERT。这意味着在触发函数中,NEWOLD 'tables' 将包含所有列值。所以从它的角度来看,user_id 总是存在的。你能做的最好的就是看看它的价值是否改变了。有关更多信息,请参阅here。您可能想查看可用的用户信息 here 并映射到 user_id 【参考方案1】:

写两个AFTER UPDATE触发器:

一个名为 trigger1AFTER UPDATE OF (user_id) 触发器仅包含 RETURN NULL

一个名为trigger2AFTER UPDATE 触发器无条件抛出错误

然后触发器将按该顺序执行,因为trigger1 按字母顺序排列在trigger2 之前。

如果user_idSET 列表中,trigger1 将执行并终止处理,因为它返回 NULL,因此trigger2 不会运行并且不会引发错误。

如果user_id 不在SET 的欲望中,trigger1 将不会运行,trigger2 将抛出错误。

有关触发器执行顺序的说明,请参阅the documentation。

【讨论】:

非常聪明,我喜欢!虽然我建议在触发器执行的顺序上添加对documentation 的引用:“如果为同一关系上的同一事件定义了多个触发器,则触发器将按触发器名称的字母顺序触发。”

以上是关于PL/PGSQL触发器如何检测UPDATE上的SQL语句中是不是提供了列?的主要内容,如果未能解决你的问题,请参考以下文章

postgresql 上的更新类型

PL/pgSQL:触发函数返回不正确的数据

使用 PL/pgSQL 检查密钥是不是存在于 JSON 中?

如何在 PL/pgSQL 中创建嵌套函数?

如何从 java 调用 pl/pgsql

如何在 PostgreSQL、PL/pgSQL 上执行匿名代码块切换 CASE 语句?