我正在编写一个在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 AlbeWHEN ( condition_on_new_and_old )
的信息吗?你的代码按预期工作。 - jian