2013-03-08 95 views
0

我正在使用postgres9.1,我一直在努力尋找一些關於如何創建視圖的教程,這些視圖可以在以後更新,並且可以在視圖中插入新行。創建一個可更新的視圖

有人可以給我一些關於如何做一個可更新的視圖,可以接受插入新行的指導?

+1

使用'而不是'觸發器:http://www.postgresql.org/docs/9.1/static/sql-createtrigger.html或在這裏看到:http://vibhorkumar.wordpress.com/2011/10/ 28 /代替-的觸發/ – 2013-03-08 17:45:14

回答

2

可更新視圖有點複雜。有兩種方法可以完成它們,一種使用RULE,另一種使用TRIGGER。觸發器造成更多的性能問題,而規則造成更細微的編碼陷阱。我將在這裏介紹兩種方法。

假設我有一個基地臺,並且提供到基臺的一部分的訪問的圖:

CREATE TABLE mybase (
     id serial primary key, 
     type_id int not null, 
     payload text not null 
); 

CREATE VIEW type1 AS select * from mybase WHERE type_id = 1; 

好的,足夠簡單。現在我們想讓視圖更新。舊的方式(維護陷阱)是使用規則:

CREATE RULE on_insert AS ON insert TO type1 
DO INSTEAD INSERT into mybase(id, type_id, payload) VALUES (new.id, 1, payload); 

CREATE RULE on_update AS ON update TO type1 
DO INSTEAD UPDATE mybase set payload = new.payload where id = old.id; 

現在,這將工作,但有一些注意事項。第一個是,如果我:

INSERT INTO type1 (id, type_id, payload) values (DEFAULT, 2, 'foo'); 

它將代之以默默輸入1而不是2。你可以讓你的代碼更加複雜,或者你可以調用一個函數來完成你的插入和更新操作,但是RULE在計劃時可以被分析到查詢中,而且函數將在每行中運行一次,所以更新可以更新一百萬使用簡單的規則,行會比函數更好地執行FAR。正確地獲取規則是複雜而棘手的,但這意味着對視圖的更新將按寫入基表的更新的方式進行擴展。

如果你有多個表,但事情變得複雜得多,因爲你有更新或刪除多行,因爲這是在計劃時間(而不是每行)合併,一方可能會被刪除,然後另一方可能無法找到需要刪除的內容。但是,如果你去功能,那麼你有刪除和更新寫入縮放問題(這基本上把你連接到重複的索引掃描循環)。

另一種選擇是使用觸發器。觸發器是被調用的每一行被寫入的函數,因此它們具有調用函數的規則的寫入縮放問題。通過這種方法,我們會創造觸發功能,並在視圖中創建觸發器:

CREATE OR REPLACE FUNCTION type1_trigger_func() RETURNS trigger LANGUAGE PLPGSQL AS 
$$ 
BEGIN 
    IF TG_OP = 'INSERT' THEN 
    IF new.type_id <> 1 THEN RAISE EXCEPTION 'Invalid type!'; END IF; 
    insert into mybasetable (id, type_id, payload) 
    VALUES (new.id, new.type_id, new.payload); 
    RETURN NEW; 
    ELSIF TG_OP = 'UPDATE' THEN 
    IF new.type_id <> 1 THEN RAISE EXCEPTION 'Invalid type!'; END IF; 
    -- update statement goes here 
    RETURN NEW; 
    ELSIF TG_IP = 'DELETE' THEN 
    DELETE FROM mybasetable WHERE id = old.id; 
    RETURN OLD; 
    END IF; 
END; 
$$; 

然後我們創建觸發器:

CREATE TRIGGER make_updateable INSTEAD OF INSERT OR UPDATE OR DELETE ON TYPE1 
FOR EACH ROW EXECUTE PROCEDURE type1_trigger_func(); 

一般來說,在這種情況下規則和觸發器的困難已經讓我瘦朝向存儲過程而不是視圖。

1

使用視圖更新數據 視圖可用於更新數據的查詢中,但受到一些限制。請記住,視圖不是一個表,也不包含任何數據 - 實際的修改始終發生在表級別。視圖不能用作覆蓋基表中定義的任何約束,規則或參照完整性的機制。

通過查看 你可以插入,更新,並在視圖中刪除行,受到以下限制更新數據限制:

如果視圖包含多個表之間的連接,你只能插入和更新視圖中的一個表,並且不能刪除行。

您不能直接修改基於聯合查詢的視圖中的數據。您不能修改使用GROUP BY或DISTINCT語句的視圖中的數據。

所有正在修改的列都受到相同的限制,就像語句直接對基表執行一樣。

無法通過視圖修改文本和圖像列。