![](/img/trans.png)
[英]Trigger to update table column when data is inserted in another table from a different database
[英]Postgresql trigger to update a column in a table when another table gets inserted or updated
基本上我有table_a和table_b。 table_b是使用table_a中的功能制成的,並且它們共同共享section_id列和狀態。
table_a的section_id是主鍵,因此它是唯一的,但是table_b可以有多個section_id,但是它們共享相同的狀態
用戶插入並更新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數據集,這是不希望的。 如何僅更新新行? 我嘗試將參數放在觸發上,但不接受new.section_id
嘗試此功能(雖然未測試)
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
上的主鍵,它才足夠。
有幾件事。 對於此類問題,訪問表定義進行測試絕對有幫助。 我已經模擬了我期望的桌子設計。 另外,包含“所需行為”也很有幫助(即,您打算始終將狀態設置為100嗎?無論table_b發生什么情況?)。 另外, update
語句必須擊中整個table_a
,這就是為什么需要唯一約束來獲得唯一記錄的原因。 如果在應將SET status = new.status
為SET status = new.status
時錯誤地將狀態設置為100,那將是一個不同的問題(但看起來更新是“擊中整個表”,請參見下面的示例-特別是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)
的new.status in (100,200)
是多余的,但是我認為您想確保安全(以防有人在沒有when
語句的情況下設置觸發器。
我的建議:如果要將表本身的狀態選項限制為100/200,我建議為僅包含這些選項的status
表創建外鍵。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.