【问题标题】:PL/PGSQL trigger how to detect if a column is provided in the SQL statement on UPDATE?PL/PGSQL触发器如何检测UPDATE上的SQL语句中是否提供了列?
【发布时间】:2023-03-03 17:13:01
【问题描述】:

我正在 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

标签: postgresql triggers plpgsql


【解决方案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 的引用:“如果为同一关系上的同一事件定义了多个触发器,则触发器将按触发器名称的字母顺序触发。”
猜你喜欢
  • 2013-03-25
  • 1970-01-01
  • 2021-02-25
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-16
相关资源
最近更新 更多