我想在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.*;
這在某種程度上可能嗎?除了審計觸發器之外,我找不到任何類似的東西,並且這些記錄只是將字符串保存爲NEW
和OLD
記錄。在這個人爲的例子中,添加新列或刪除它們會很簡單,因爲base
/sub
表會發生變化,但只要有更多的子表和更多的列,這些變得實際上不可維護。
爲什麼不使用PostgreSQL的本地[TABLE繼承](http://www.postgresql.org/docs/9.4/static/ddl-inherit.html)?你可以讓你的所有子表繼承自基本表,並直接寫入查詢,不需要VIEWS和TRIGGERS。 – Eggplant
因爲文檔說它不支持繼承外鍵或主鍵,這是我需要的最重要的方面之一。 – milch
你可以編寫一個觸發器,用動態SQL做這件事。您將針對'information_schema'使用查詢來查找哪些列是哪些表的一部分,並使用'EXECUTE format(...)USING(...)'來準備SQL。動態訪問來自'NEW'的列是可能的,但很尷尬。總的來說,這將是緩慢和痛苦的,但它會工作。真的,最好的辦法是在C中實現觸發器,在那裏你可以使用PostgreSQL relcache,heap_form_tuple等等,但這很先進。 –