PostgreSQL中在AFTER TRIGGER函数中对IF条件进行评估

4

我正在编写一个在PostgreSQL中(版本10)通过TRIGGER AFTER UPDATE调用的plpgsql函数。

  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未找到'的异常抛出。

注意到触发器以前是在UPDATE之前运行并且按预期工作,但当我们将其设置为AFTER时出现了问题。

我相信我对AFTER触发器的行为有所遗漏。你有什么想法吗?

提前感谢大家。


使用 RAISE NOTICE 显示您在 IF 条件中使用的所有变量。 - Laurenz Albe
请提供您正在使用的UPDATE数据。 - Adrian Klaver
你能分享更多关于 WHEN ( condition_on_new_and_old ) 的信息吗?你的代码按预期工作。 - jian
https://dbfiddle.uk/fnM7Y0Us 这是我的测试演示。 - jian
1个回答

0
感谢对问题的评论。很抱歉,我在日志中没有注意到触发器的WHEN条件实际上存在问题。
修复后,它已经正常工作了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接