2016-12-03 71 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! 
    ...); 

關於連接字符串:

而且我也不會用駝峯標識: