Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何停止重复列名而不是PostgreSQL中的触发器?_Sql_Postgresql - Fatal编程技术网

如何停止重复列名而不是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上如何解决继承不需要考

我试图从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.*;

这有可能吗?我找不到任何类似的东西,除了审计触发器,它们只是将新记录和旧记录保存为字符串。在这个人为设计的示例中,随着基表/子表的更改,添加或删除新的列将非常容易,但一旦有更多的子表和列,这实际上就变得无法维护

就像克雷格建议的那样,我最终直接在应用程序中解决了它,而不是在数据库中。我的应用程序知道视图中的所有相关列以及基本类型,因此在迁移过程中创建触发器和视图就更容易了。

为什么不使用PostgreSQL的本机?您可以让所有子表从基表继承,并编写直接引用它们的查询,不需要视图或触发器。因为文档中说它不支持继承外键或主键,这是我需要的最重要的方面之一。您可能可以编写一个触发器,用动态SQL实现这一点。您将使用对信息模式的查询来找出哪些列是哪些表的一部分,并执行format。。。使用。。。准备SQL。从NEW动态访问列是可能的,但很尴尬。总的来说,这将是缓慢和痛苦的,但它会工作。实际上,最好的方法是在C中实现触发器,您可以使用PostgreSQL relcache、heap\u form\u tuple等,但这非常高级。或者,您仍然可以使用表继承:创建一个子表生成函数,该函数执行一些动态sql来生成子表,并定义基本表所需的主键和外键。然后,您可以使用一些触发器来处理子表和基表之间所需的唯一性。这对于实现来说是微不足道的,因为列只依赖于基表,而且性能也相当好,因为它将查询两个表中的索引。触发器也将通过sub_table_生成函数连接到sub_table。