如何停止重复列名而不是PostgreSQL中的触发器?
我试图从PostgreSQL中的实体关系模型创建一个简单的表继承层次结构 为此,我创建了以下表格:如何停止重复列名而不是PostgreSQL中的触发器?,sql,postgresql,Sql,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上如何解决继承不需要考
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.*;
这有可能吗?我找不到任何类似的东西,除了审计触发器,它们只是将新记录和旧记录保存为字符串。在这个人为设计的示例中,随着基表/子表的更改,添加或删除新的列将非常容易,但一旦有更多的子表和列,这实际上就变得无法维护 就像克雷格建议的那样,我最终直接在应用程序中解决了它,而不是在数据库中。我的应用程序知道视图中的所有相关列以及基本类型,因此在迁移过程中创建触发器和视图就更容易了。为什么不使用PostgreSQL的本机?您可以让所有子表从基表继承,并编写直接引用它们的查询,不需要视图或触发器。因为文档中说它不支持继承外键或主键,这是我需要的最重要的方面之一。您可能可以编写一个触发器,用动态SQL实现这一点。您将使用对信息模式的查询来找出哪些列是哪些表的一部分,并执行format。。。使用。。。准备SQL。从NEW动态访问列是可能的,但很尴尬。总的来说,这将是缓慢和痛苦的,但它会工作。实际上,最好的方法是在C中实现触发器,您可以使用PostgreSQL relcache、heap\u form\u tuple等,但这非常高级。或者,您仍然可以使用表继承:创建一个子表生成函数,该函数执行一些动态sql来生成子表,并定义基本表所需的主键和外键。然后,您可以使用一些触发器来处理子表和基表之间所需的唯一性。这对于实现来说是微不足道的,因为列只依赖于基表,而且性能也相当好,因为它将查询两个表中的索引。触发器也将通过sub_table_生成函数连接到sub_table。