当插入或更新另一个表时,Postgresql触发器更新表中的列

时间:2017-08-04 10:31:35

标签: sql postgresql

基本上我有table_a和table_b。 table_b由table_a中的功能组成,共同的是它们共享section_id列和状态。

table_a的section_id是主键,因此它是唯一的,但table_b可以有多个section_ids,但它们都共享相同的状态

用户插入并更新table_b,我想在table_a

中捕获状态更改
CREATE TRIGGER table_b_aiu
AFTER INSERT OR UPDATE
ON table_b
FOR EACH ROW
WHEN (((new.status = 100) OR (new.status = 200)))
EXECUTE PROCEDURE table_b_aiu();

CREATE OR REPLACE FUNCTION table_b_aiu()
RETURNS trigger AS
$BODY$
BEGIN
UPDATE table_a a
SET status = 100
FROM table_b b
WHERE (b.status = 100 or b.status = 200) 
AND a.section_id = b.section_id;
    RETURN new; 
END;
$BODY$
 LANGUAGE plpgsql VOLATILE
 COST 100;

问题在于,它不是仅仅更新新更新或插入的行,而是更新ENTIRE数据集,这不是预期的。如何只更新新行?我已经尝试在triger上设置参数但它不接受new.section_id

2 个答案:

答案 0 :(得分:1)

尝试此功能(尽管未经过测试)

CREATE OR REPLACE FUNCTION table_b_aiu()
RETURNS trigger AS
$BODY$
BEGIN
    UPDATE table_a
    SET status = 100
    WHERE section_id = NEW.section_id
    RETURN new;
END;
$BODY$

section_id成为table_a上的主键之前,它应该足够了。

答案 1 :(得分:1)

所以有几件事。对于这类问题,访问表定义进行测试肯定是有帮助的。我嘲笑了我期望的桌子设计。此外,包含“期望的行为”是有帮助的(即,您是否打算始终将状态设置为100?无论table_b发生什么情况?)。此外,update语句必然会命中整个table_a,这就是您需要唯一约束来获取唯一记录的原因。如果您错误地将状态设置为100,那么它应该是SET status = new.status,这将是一个不同的问题(但可能看起来更新是“击中整个表格”,请参阅下面的示例 - 特别是{{1} })。

希望以下说明准确的行为。我怀疑你的触发器应该设置section_id=3

status=new.status

注意:CREATE TABLE table_a ( section_id serial , status integer , CONSTRAINT pk_table_a PRIMARY KEY (section_id) ); CREATE TABLE table_b ( id serial , section_id integer , status integer , CONSTRAINT pk_table_b_aiu PRIMARY KEY (id) ) ; CREATE OR REPLACE FUNCTION table_b_aiu() RETURNS trigger AS $BODY$ BEGIN UPDATE table_a a SET status = 100 -- intentional?? WHERE (new.status = 100 or new.status = 200) AND a.section_id = new.section_id; RETURN new; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; CREATE TRIGGER table_b_aiu AFTER INSERT OR UPDATE ON table_b FOR EACH ROW WHEN (((new.status = 100) OR (new.status = 200))) EXECUTE PROCEDURE table_b_aiu(); INSERT INTO table_a (section_id, status) values (1,100) , (2,200) , (3,201) , (4, 202) returning *; | section_id | status | | 1 | 100 | | 2 | 200 | | 3 | 201 | | 4 | 202 | INSERT INTO table_b (section_id, status) values (1,101), (2,100), (3,200), (4,201) returning *; | id | section_id | status | | 1 | 1 | 101 | | 2 | 2 | 100 | | 3 | 3 | 200 | | 4 | 4 | 201 | select * from table_a; | section_id | status | | 1 | 100 | | 4 | 202 | | 2 | 100 | | 3 | 100 | 是多余的,但我认为你想要安全(以防有人在没有new.status in (100,200)语句的情况下设置触发器。

我的建议:如果你想将表本身的状态选项限制为100/200,我建议为只有这些选项的when表创建一个外键。