2016-12-03 70 views
0

我有两个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.nameA.column_A的值的串联:

B.keywords := B.name || A.column_A 

如何在表B与触发更新每个行的列B.keywords如果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; 

回答

1

,您的触发有呼叫时,被更新的功能:

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以设置关键字很有用。

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! 
    ...); 

关于连接字符串:

而且我也不会用驼峰标识: