是否可以动态循环表的列?
我有一个用于表测试的触发器函数,其中包含以下代码片段:
IF TG_OP='UPDATE' THEN
IF OLD.locked > 0 AND
( OLD.org_id <> NEW.org_id OR
OLD.document_code <> NEW.document_code OR
-- other columns ...
)
THEN
RAISE EXCEPTION 'Message';
-- more code
因此,我静态检查所有列的新值及其先前的值,以确保完整性。现在,每当我的业务逻辑发生变化并且我必须向该表中添加新列时,我每次都必须修改此触发器。我认为如果我可以动态检查该表的所有列,而无需显式键入它们的名称,那就更好了。
怎么办呢?
I have a trigger function for a table test which has the following code snippet:
IF TG_OP='UPDATE' THEN
IF OLD.locked > 0 AND
( OLD.org_id <> NEW.org_id OR
OLD.document_code <> NEW.document_code OR
-- other columns ...
)
THEN
RAISE EXCEPTION 'Message';
-- more code
So I am statically checking all the column's new value with its previous value to ensure integrity. Now every time my business logic changes and I have to add new columns into that table, I will have to modify this trigger each time. I thought it would be better if somehow I could dynamically check all the columns of that table, without explicitly typing their name.
How can it be done?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
从 9.0 beta2 文档开始,有关触发器中
WHEN
子句的文档可能可以在触发器主体中的早期版本中使用:OLD.* IS DISTINCT FROM NEW.*
或可能(来自 8.2 发行说明)
IF 行(新。*)与行(旧。*)不同
From 9.0 beta2 documentation about
WHEN
clause in triggers, which might be able to be used in earlier versions within the trigger body:OLD.* IS DISTINCT FROM NEW.*
or possibly (from 8.2 release notes)
IF row(new.*) IS DISTINCT FROM row(old.*)
看一下information_schema,有一个视图“columns”。执行查询以从触发触发器的表中获取所有当前列名:
循环遍历结果即可!
更多信息可以在精细手册中找到。
Take a look at the information_schema, there is a view "columns". Execute a query to get all current columnnames from the table that fired the trigger:
Loop through the result and there you go!
More information can be found in the fine manual.
在 Postgres 9.0 或更高版本中添加
WHEN
子句到您的触发器定义(CREATE TRIGGER
语句):仅适用于触发器
BEFORE
/AFTER
UPDATE
,其中定义了OLD
和NEW
。尝试将此WHEN
子句与INSERT
或DELETE
触发器一起使用时,您会遇到异常。并相应地从根本上简化触发器功能:
无需测试
IF TG_OP='UPDATE' ...
,因为该触发器仅适用于UPDATE
。或者也将该条件移到 WHEN 子句中:
在触发函数中仅留下无条件的 RAISE EXCEPTION ,该函数仅在需要时才调用。
阅读细则:
相关:
还要解决问题标题
是的。示例:
In Postgres 9.0 or later add a
WHEN
clause to your trigger definition (CREATE TRIGGER
statement):Only possible for triggers
BEFORE
/AFTER
UPDATE
, where bothOLD
andNEW
are defined. You'd get an exception trying to use thisWHEN
clause withINSERT
orDELETE
triggers.And radically simplify the trigger function accordingly:
No need to test
IF TG_OP='UPDATE' ...
since this trigger only works forUPDATE
anyway.Or move that condition in the WHEN clause, too:
Leaving only an unconditional
RAISE EXCEPTION
in your trigger function, which is only called when needed to begin with.Read the fine print:
Related:
To also address the question title
Yes. Examples:
触发器内 RECORD 变量的迭代
Iteration over RECORD variable inside trigger
使用 pl/perl 或 pl/python。他们更适合此类任务。 好多了更好。
您还可以安装 hstore-new ,并使用它的 row->hstore 语义,但是当使用普通数据类型时,这绝对不是一个好主意。
Use pl/perl or pl/python. They are much better suited for such tasks. much better.
You can also install hstore-new, and use it's row->hstore semantics, but that's definitely not a good idea when using normal datatypes.