更新columnA或ColumnB或ColumnC时触发触发器

Mar*_*tin 18 postgresql triggers constraints notify

我有代码只在更新单个特定列时触发触发器.触发器用于触发一个函数,该函数将引发一个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();
Run Code Online (Sandbox Code Playgroud)

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

WHEN (OLD.email IS DISTINCT FROM NEW.email OR 
OLD.username IS DISTINCT FROM NEW.username OR 
OLD.password IS DISTINCT FROM NEW.password) 
Run Code Online (Sandbox Code Playgroud)

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

Erw*_*ter 29

这是一种误解.WHEN触发器定义boolean子句需要一个表达式,您可以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();
Run Code Online (Sandbox Code Playgroud)

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

CREATE TRIGGER ... AFTER UPDATE OF email, username, password ...
Run Code Online (Sandbox Code Playgroud)

因为,根据文件:

当列的UPDATE OFcolumn_name 任何列在UPDATE命令SET列表中列为目标时,将触发特定于列的触发器(使用语法定义的触发器) .即使未触发触发器,列的值也可能会更改,因为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();
Run Code Online (Sandbox Code Playgroud)

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

...
WHEN (OLD IS DISTINCT FROM NEW)
...
Run Code Online (Sandbox Code Playgroud)

  • @malthe:不适用于这个特定问题,但我添加了它以使其完整.我建议使用更短,等效的语法:`WHEN(OLD IS DISTINCT FROM NEW)` - 括号是必需的.在此期间,我还在那里添加了另一个答案...... (2认同)

a_h*_*ame 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();
Run Code Online (Sandbox Code Playgroud)

  • 我有一种感觉,当通过 UPDATE sql 语句设置值时,这会触发,无论它们是否被认为是“更新”,即不同。 (2认同)