基本上我有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
答案 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
表创建一个外键。