更新列或列或ColumnS时触发触发器

问题描述 投票:14回答:2

我有代码只在更新单个特定列时触发触发器。触发器用于触发一个函数,该函数将引发一个postgres“notify”事件,我正在监听它,并且需要测试并验证新输入的详细信息。 account_details表上有许多值可以更改,不需要帐户验证,因此仅在AFTER UPDATE(没有时间)的触发器是不好的。

    CREATE TRIGGER trigger_update_account_details
    AFTER UPDATE ON account_details
    FOR EACH ROW
    WHEN (OLD.email IS DISTINCT FROM NEW.email) 
    EXECUTE PROCEDURE notify_insert_account_details();

但是,如果许多列中的一个发生变化,我想触发触发器

WHEN (OLD.email IS DISTINCT FROM NEW.email OR 
OLD.username IS DISTINCT FROM NEW.username OR 
OLD.password IS DISTINCT FROM NEW.password) 

但OR不是触发器的有效关键字。试图搜索要使用的关键字而不是OR似乎没有提出任何由于单词OR的性质:-(

postgresql triggers constraints notify
2个回答
26
投票

这是一种误解。 WHEN clause of the trigger definition expects a boolean expression,你可以使用OR运算符。这应该工作(假设所有列实际存在于表account_details中)。我自己使用类似的触发器:

CREATE TRIGGER trigger_update_account_details
AFTER UPDATE ON account_details
FOR EACH ROW
WHEN (OLD.email    IS DISTINCT FROM NEW.email
   OR OLD.username IS DISTINCT FROM NEW.username
   OR OLD.password IS DISTINCT FROM NEW.password) 
EXECUTE PROCEDURE notify_insert_account_details();

评估表达式的成本很低,但这可能比替代方案更可靠:

CREATE TRIGGER ... AFTER UPDATE OF email, username, password ...

因为,per documentation

当列的任何列在UPDATE OF命令的column_name列表中列为目标时,将触发特定于列的触发器(使用UPDATESET语法定义的触发器)。即使未触发触发器,列的值也可能会更改,因为不考虑BEFORE UPDATE触发器对行内容所做的更改。相反,像UPDATE ... SET x = x ...这样的命令会在列x上触发一个触发器,即使该列的值没有改变。

ROW类型语法更短,可以检查许多列(做同样的事情):

CREATE TRIGGER trigger_update_account_details
AFTER UPDATE ON account_details
FOR EACH ROW
WHEN ((OLD.email, OLD.username, OLD.password, ...)
       IS DISTINCT FROM
      (NEW.email, NEW.username, NEW.password, ...))
EXECUTE PROCEDURE notify_insert_account_details();

或者,检查行中的每个可见用户列:

...
WHEN (OLD IS DISTINCT FROM NEW)
...

7
投票

我认为你不需要WHEN条款。您可以在UPDATE子句中指定有问题的列:

CREATE TRIGGER trigger_update_account_details
    AFTER UPDATE OF email, username, password ON account_details
    FOR EACH ROW
    EXECUTE PROCEDURE notify_insert_account_details();
© www.soinside.com 2019 - 2024. All rights reserved.