在Postgres中,当通过一个BEFORE触发器中的NEW对象更改表中的字段时,如何执行触发器来更改该字段?
示例: 第一个触发器“trigger1”:
CREATE OR REPLACE FUNCTION trigger1()
RETURNS trigger
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
--...
NEW.time_spent = NEW.etime - NEW.stime;
NEW.cost := NEW.time_spent * NEW.rate; -- field "cost" has been changed!
RETURN NEW;
END;
$BODY$;
CREATE TRIGGER before_100_calc_cost BEFORE INSERT OR UPDATE OF stime, etime ON table1 FOR EACH ROW EXECUTE PROCEDURE trigger1();
第二个触发器“trigger2”,由于某种原因没有执行:
CREATE OR REPLACE FUNCTION trigger2()
RETURNS trigger
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
RAISE NOTICE 'trigger "trigger2" did not start!((';
-- some actions...
END;
$BODY$;
CREATE TRIGGER after_104_calc_parent_cost AFTER INSERT OR UPDATE OF cost OR DELETE ON table1 FOR EACH ROW EXECUTE PROCEDURE trigger2();
表1:
CREATE TABLE IF NOT EXISTS table1 (
id serial PRIMARY KEY,
parent_id integer,
stime timestamptz NOT NULL DEFAULT NOW(),
etime timestamptz DEFAULT NULL,
time_spent real DEFAULT NULL,
rate numeric204 DEFAULT NULL,
cost numeric204 DEFAULT NULL
);
测试用例:
INSERT INTO table1 (stime) VALUES (NOW() - INTERVAL '1 hour');
UPDATE table1 SET etime = NOW(); -- trigger "trigger2" did not start!
当执行“trigger1”并且“cost”字段更改时,触发器“trigger2”不会触发!
如果修复数据类型,第二个触发器中缺少
return
,它将按预期工作。初始 insert
会触发两个触发器,然后更新仅触发 trigger1
,因为虽然它确实尝试更改 cost
,但它不在 update
语句的目标列中,并且触发器定义为仅在以下情况下触发:是(update or insert
of cost
)。引用CREATE TRIGGER
文档:
它还将它从对于
事件,可以使用以下语法指定列列表:UPDATE
UPDATE OF column_name1 [, column_name2 ... ]
仅当至少列出的列之一被提及为
命令的目标,或者列出的列之一是依赖于作为 的目标的列的生成列时,触发器才会触发UPDATE
UPDATE
。
null
null
,因此您也无法通过比较 NEW
与
OLD
来理解它。您留下
rate
没有默认值,并且没有将其填充到插入、更新或触发器中,因此它使应该改变成本的表达式无效。我猜你希望每当有任何东西以任何方式接触到该字段时
update of cost
就会触发并更新它,但事实并非如此。