2016-12-13 44 views
0

我試圖在PostgreSQL視圖上調用insertupdate調用表。下面是我做的一個簡單的例子:如何通過觸發和插入過程將數據插入視圖時避免「空白」插入?

[Person] table: 
id | lastname | firstname | city | age 

[Person_View] table: 
id | lastname | firstname | city 

這裏是觸發和相關程序:

CREATE TRIGGER tg_update_person_view 
    INSTEAD OF INSERT OR UPDATE OR DELETE ON 
     Person_View FOR EACH ROW EXECUTE PROCEDURE update_person_view_table(); 

CREATE OR REPLACE FUNCTION update_person_view_table() 
RETURNS TRIGGER 
LANGUAGE plpgsql 
AS $function$ 
    BEGIN 
     IF TG_OP = 'INSERT' THEN 
     INSERT INTO Person (id, lastname, firstname) 
     VALUES(NEW.id, NEW.lastname, NEW.firstname); 
     RETURN NEW; 
     ELSIF TG_OP = 'UPDATE' THEN 
     UPDATE Person 
     SET id=NEW.id, lastname=NEW.lastname, firstname=NEW.firstname 
     WHERE id=OLD.id; 
     RETURN NEW; 
     END IF; 
     RETURN NEW; 
    END; 
$function$; 

如果我做的:

INSERT INTO Person_View (id, city) VALUES ('3', 'Berlin') 

一隻有ID的行被添加到視圖和父表中。

如何檢查過程中插入值的列是否具有在過程中定義的「映射」,並且如果沒有任何映射列,則不會繼續?

+0

在Postgres裏9.3+你不需要規則,也不會觸動,基於單個表的視圖自動更新。 – klin

+0

我知道,我應該說這個簡化的例子是可以自動更新的。我的真實情況是,我有基於多個表的視圖,我不希望這些空記錄發生。 – kaycee

回答

1

您可以定義表上的檢查約束,例如:

create table person(
    id int primary key, 
    lastname text, 
    firstname text, 
    city text, 
    age int, 
    check(coalesce(lastname, firstname, city, age::text) is not null) 
); 

insert into person (id) 
values (1); 

ERROR: new row for relation "person" violates check constraint "person_check" 
DETAIL: Failing row contains (1, null, null, null, null). 

解決方案的工作無論是創建或不基於表的任何意見。

1

單獨觸發&觸發功能爲ON DELETE來簡化。 (你沒有做任何事情ON DELETE呢?)

一個CHECK約束像klin suggested似乎是一個不錯的主意。不過,你不需要COALESCE。檢查一個值爲NULL。

CHECK (NOT ROW(lastname, firstname) IS NULL) -- ROW keyword is noise 

這加強了該行中的至少一個NOTNULL值。適用於任意數量的列和任何數據類型。

特別注意,ROW(lastname, firstname) IS NOT NULL是不一樣的,不會工作。詳細說明:

如果CHECK約束不是一個選項,您可以使用觸發器一樣的表情 - 這應該是比它添加到觸發功能更快。 The manual on CREATE TRIGGER:

Also, a trigger definition can specify a Boolean WHEN condition, which will be tested to see whether the trigger should be fired. In row-level triggers the WHEN condition can examine the old and/or new values of columns of the row.

CREATE TRIGGER tg_update_person_view 
INSTEAD OF INSERT OR UPDATE ON Person_View 
FOR EACH ROW 
WHEN (NOT (NEW.lastname, NEW.firstname) IS NULL) -- more columns? 
EXECUTE PROCEDURE update_person_view_table(); 

如果WHEN表達式的值不以TRUE,觸發功能甚至不叫 - 因此它does not proceed像要求。


但是,我錯過了你的觸發器是INSTEAD OFThe manual:

INSTEAD OF triggers do not support WHEN conditions.

在這種情況下,你必須檢查進入的函數體:

IF NOT (NEW.lastname, NEW.firstname) IS NULL THEN 
    -- do stuff 
END IF; 
+0

我得到這個錯誤:'錯誤:INSTEAD OF觸發器不能在條件********** **********錯誤'。 – kaycee

+0

@ kaycee:哦,對不起。不適用於INSTEAD觸發器。在這種情況下,您必須將支票移入功能。 (你認爲'CHECK'約束?) –