Postgres - 通过 NEW

问题描述 投票:0回答:1

在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”不会触发!

postgresql triggers
1个回答
0
投票

如果修复数据类型,第二个触发器中缺少

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

 就会触发并更新它,但事实并非如此。

© www.soinside.com 2019 - 2024. All rights reserved.