【发布时间】:2022-09-24 18:00:31
【问题描述】:
我正在 PostgreSQL(版本 10)中编写一个由 TRIGGER 调用的 plpgsql 函数后更新
CREATE TRIGGER trigger_1
AFTER UPDATE
ON entities
FOR EACH ROW
WHEN ( condition_on_new_and_old )
EXECUTE PROCEDURE function_1();
实体是一个表,它有一个 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 触发器的行为方式的信息。你有什么想法?
谢谢大家
-
执行
RAISE NOTICE以显示您在IF条件中使用的所有变量。 -
还要提供您正在使用的 UPDATE 数据。
-
您能否分享有关
WHEN ( condition_on_new_and_old )的更多信息。您的代码按预期工作。 -
dbfiddle.uk/fnM7Y0Us我的测试演示。
标签: sql postgresql if-statement triggers