我有两个Postgres表:
create table A(
id_A serial not null,
column_A varchar null;
...);
create table B(
id_B serial not null,
id_A int4 not null,
name varchar null,
keywords varchar null,
...);
表A
的元素与表B
的多个元素相关联,表B
的元素与表A
的一个元素相关联。
表B
中的列关键字是列B.name
和A.column_A
的值的串联:
B.keywords := B.name || A.column_A
如果更新B.keywords
的值,如何使用触发器更新表B
中每行的A.column_A
列?
换句话说,我想做这样的事情(伪代码):
FOR EACH ROW current_row IN TABLE B
UPDATE B SET keywords = (SELECT B.name || A.column_A
FROM B INNER JOIN A ON B.id_A = A.id_A
WHERE B.id_B = current_row.id_B)
WHERE id_B = current_row.id_B;
答案 0 :(得分:1)
当A更新时,你的触发器必须调用一个函数:
CREATE OR REPLACE FUNCTION update_b()
RETURNS TRIGGER
AS $$
BEGIN
UPDATE B
SET keywords = name || NEW.column_A
WHERE id_A = NEW.id_A;
return NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_b_trigger AFTER UPDATE OF column_A
ON A
FOR EACH ROW
EXECUTE PROCEDURE update_b();
在表B上添加触发器BEFORE INSERT OR UPDATE
以设置关键字也可能很有用。
答案 1 :(得分:0)
你的方法被设计破坏了。不要试图在表中保持派生值是最新的。这对于并发访问来说并不安全。可能出现各种并发症。您膨胀表B
(和备份)并削弱写入性能。
相反,请使用VIEW
(或MATERIALIZED VIEW
):
CREATE VIEW ab AS
SELECT B.*, concat_ws(', ', B.name, A.column_A) AS keywords
FROM B
LEFT JOIN A USING (id_A);
使用下面的更新表定义,保证了参照完整性,您可以使用[INNER] JOIN
代替LEFT [OUTER] JOIN
。
甚至一个简单的查询就足够了......
无论哪种方式,您需要表A
中的PRIMARY KEY
constraint和表B
中的FOREIGN KEY
constraint:
CREATE TABLE A (
id_A serial PRIMARY KEY,
column_A varchar
...);
CREATE TABLE B (
id_B serial PRIMARY KEY,
id_A int4 NOT NULL REFERENCES A(id_A),
name varchar
-- and *no* redundant "keywords" column!
...);
关于串联字符串:
我不会使用CaMeL案例标识符: