2015-09-07 16 views
0

我想在PostgreSQL中從我的實體關係模型創建一個簡單的表繼承層次結構。而不是PostgreSQL中的觸發器,我該如何停止重複列名?

對於這一點,我已經創建了下面的表格:

CREATE TABLE base (
    id integer PRIMARY KEY, 
    title varchar(40), 
    test integer 
); 

CREATE TABLE sub (
    id integer REFERENCES base(id) PRIMARY KEY, 
    count integer 
); 

現在,由於如何繼承解決在DB並不需要關注的應用,我還創建了一個觀點,即應用程序將訪問。應用程序中的所有操作都應該在視圖上執行,因此我還需要使用instead of觸發器來執行更新,插入和刪除操作。視圖定義和觸發看起來是這樣的:

CREATE VIEW sub_view AS 
    SELECT s.count, b.title, b.test, b.id FROM sub s 
    JOIN base b ON b.id = s.id; 

--TRIGGER 
CREATE OR REPLACE FUNCTION instead_of_f() 
    RETURNS trigger AS 
$$ 
BEGIN 
    IF TG_OP = 'INSERT' THEN 
     INSERT INTO base(id, title, test) VALUES (NEW.id, NEW.title, NEW.test); 
     INSERT INTO sub(id, test) VALUES (NEW.id, NEW.test); 
     RETURN NEW; 
    ELSIF TG_OP = 'UPDATE' THEN 
     UPDATE base SET title = NEW.title, test = NEW.test WHERE id = OLD.id; 
     UPDATE sub SET count = NEW.count WHERE id = OLD.id; 
     RETURN NEW; 
    ELSIF TG_OP = 'DELETE' THEN 
     DELETE FROM sub WHERE id = OLD.id; 
     DELETE FROM base WHERE id = OLD.id; 
     RETURN NULL; 
    END IF; 
END; 
$$ LANGUAGE PLPGSQL; 

CREATE TRIGGER instead_of_dml_trig 
    INSTEAD OF INSERT OR UPDATE OR DELETE ON 
     sub_view FOR EACH ROW 
     EXECUTE PROCEDURE instead_of_f(); 

這基本上能正常工作,但它是乏味和並不十分維護不得不一遍又一遍地重複所有的列名。理想情況下,我想寫點東西像這樣的觀點,而不是:

CREATE VIEW sub_view AS 
    SELECT * FROM sub s JOIN base b ON b.id = s.id; 

,而是在觸發器的INSERT語句:

INSERT INTO base VALUES NEW.*; 
INSERT INTO sub VALUES NEW.*; 

這在某種程度上可能嗎?除了審計觸發器之外,我找不到任何類似的東西,並且這些記錄只是將字符串保存爲NEWOLD記錄。在這個人爲的例子中,添加新列或刪除它們會很簡單,因爲base/sub表會發生變化,但只要有更多的子表和更多的列,這些變得實際上不可維護。

+0

爲什麼不使用PostgreSQL的本地[TABLE繼承](http://www.postgresql.org/docs/9.4/static/ddl-inherit.html)?你可以讓你的所有子表繼承自基本表,並直接寫入查詢,不需要VIEWS和TRIGGERS。 – Eggplant

+1

因爲文檔說它不支持繼承外鍵或主鍵,這是我需要的最重要的方面之一。 – milch

+0

你可以編寫一個觸發器,用動態SQL做這件事。您將針對'information_schema'使用查詢來查找哪些列是哪些表的一部分,並使用'EXECUTE format(...)USING(...)'來準備SQL。動態訪問來自'NEW'的列是可能的,但很尷尬。總的來說,這將是緩慢和痛苦的,但它會工作。真的,最好的辦法是在C中實現觸發器,在那裏你可以使用PostgreSQL relcache,heap_form_tuple等等,但這很先進。 –

回答

0

和克雷格一樣,我最終直接在應用程序中解決問題,而不是在數據庫中解決問題。我的應用程序知道視圖中的所有相關列以及基本類型,因此最終在這些遷移中創建觸發器和視圖變得更加容易。