PostgreSQL 上 AFTER TRIGGER 函数中的 IF 条件计算

IF condition evaluation in AFTER TRIGGER function on PostgreSQL

提问人:dariush624 提问时间:9/23/2022 更新时间:9/24/2022 访问量:110

问:

我正在 PostgreSQL(版本 10)中编写一个 plpgsql 函数,该函数在 UPDATE 由 TRIGGER 调用

  CREATE TRIGGER trigger_1
   AFTER UPDATE
   ON entities
   FOR EACH ROW
   WHEN ( condition_on_new_and_old )
   EXECUTE PROCEDURE function_1();

entities 是一个表,它有一个 JSONB 类型的列。data

function_1的代码本质上是(我修改了代码以隔离IF中的RAISE,最初条件是相反的):

CREATE OR REPLACE FUNCTION function_1() RETURNS TRIGGER AS
$$
BEGIN
  IF (
       TG_OP <> 'UPDATE' 
       OR TG_WHEN <> 'AFTER'
       OR NOT (NEW.data ? 'XXX')
       OR NOT (OLD.data ? 'XXX')
       OR NOT (NEW.object_id = OLD.object_id)
       OR NOT (NEW.workspace = OLD.workspace)) THEN

         RAISE EXCEPTION 'XXX not found';

  END IF;

  -- SOME INSERTs

  -- SOME DELETEs

  RETURN NULL;
END
$$ LANGUAGE plpgsql;

正如每个人都可以预料的那样,如果 IF 中的条件为真,我们会提出异常。问题是,无论条件的值如何,RAISE 始终被执行。在我所有的测试中,OLD 和 NEW 的值始终相同。

更令人惊讶的是,如果我做了这样的事情

CREATE OR REPLACE FUNCTION function_1() RETURNS TRIGGER AS
$$
BEGIN
  IF (
       TG_OP <> 'UPDATE' 
       OR TG_WHEN <> 'AFTER'
       OR NOT (NEW.data ? 'XXX')
       OR NOT (OLD.data ? 'XXX')
       OR NOT (NEW.object_id = OLD.object_id)
       OR NOT (NEW.workspace = OLD.workspace)) THEN

         RAISE EXCEPTION 'XXX not found';

  END IF;

  RAISE EXCEPTION 'TEST'

  -- SOME INSERTs

  -- SOME DELETEs

  RETURN NULL;
END
$$ LANGUAGE plpgsql;

我提出了异常“TEST”,但如果我写:

CREATE OR REPLACE FUNCTION function_1() RETURNS TRIGGER AS
$$
BEGIN
  IF (
       TG_OP <> 'UPDATE' 
       OR TG_WHEN <> 'AFTER'
       OR NOT (NEW.data ? 'XXX')
       OR NOT (OLD.data ? 'XXX')
       OR NOT (NEW.object_id = OLD.object_id)
       OR NOT (NEW.workspace = OLD.workspace)) THEN

         RAISE EXCEPTION 'XXX not found';

  END IF;

  -- RAISE EXCEPTION 'TEST' (I commented the RAISE)

  -- SOME INSERTs

  -- SOME DELETEs

  RETURN NULL;
END
$$ LANGUAGE plpgsql;

我抛出了异常“XXX not found”。

要注意触发器曾经处于 BEFORE UPDATE 状态并且它确实按预期工作,当我们将其设置为 AFTER 时,问题就出现了。

我很确定我错过了一些关于 AFTER 触发器行为的信息。你有什么想法吗?

提前谢谢大家

SQL PostgreSQL IF-statement 触发器

评论

0赞 Laurenz Albe 9/23/2022
执行 a 以显示您在条件中使用的所有变量。RAISE NOTICEIF
0赞 Adrian Klaver 9/23/2022
同时提供您正在使用的 UPDATE 数据。
0赞 jian 9/24/2022
您能否分享有关的更多信息。您的代码正在按预期工作。WHEN ( condition_on_new_and_old )
0赞 jian 9/24/2022
dbfiddle.uk/fnM7Y0Us 我的测试演示。

答:

0赞 dariush624 9/24/2022 #1

感谢您对这个问题的评论。对不起,但我没有在日志中注意到 TRIGGER 的状况实际上存在问题。WHEN

修复它后,它就可以工作了。