具有非null约束的Postgresql可更新视图

时间:2017-01-23 23:51:37

标签: postgresql

在我的测试应用程序中,我在CREATE TABLE public.parties ( id integer NOT NULL DEFAULT nextval('parties_id_seq'::regclass), party_type_id text NOT NULL, fullname text NOT NULL DEFAULT ''::text, created_at timestamp without time zone NOT NULL DEFAULT now(), CONSTRAINT parties_pkey PRIMARY KEY (id, party_type_id), (... extra sql not relevant to the question ...) ); CREATE TABLE public.party_people ( id integer NOT NULL, gender text NOT NULL DEFAULT ''::text, CONSTRAINT party_people_pkey PRIMARY KEY (id), (... extra sql not relevant to the question ...) ); CREATE OR REPLACE VIEW public.people AS SELECT t1.id, t1.party_type_id, t1.fullname, t2.gender, t1.created_at FROM parties t1 JOIN party_people t2 ON t1.id = t2.id; CREATE OR REPLACE FUNCTION public.people_vw_update_func() RETURNS trigger AS LANGUAGE plpgsql $BODY$ BEGIN IF TG_OP = 'INSERT' THEN IF NEW.id IS NULL THEN NEW.id = NEXTVAL('parties_id_seq'); END IF; INSERT INTO parties VALUES (NEW.id, NEW.party_type_id, NEW.fullname, NEW.created_at); INSERT INTO party_people VALUES (NEW.id, NEW.party_type_id, NEW.gender); RETURN NEW; ELSIF (... extra sql to deal with DELETE and UPDATE cases ...) END IF; RETURN NEW; END; $BODY$ CREATE TRIGGER people_vw_update_trig INSTEAD OF INSERT OR UPDATE OR DELETE ON people FOR EACH ROW EXECUTE PROCEDURE people_vw_update_func(); 实例上有以下设置的数据库。

people

我试图在postgres中创建一个可更新的视图,我可以通过NON NULL视图管理人员数据,而不是手动编写查询来跨两个表分割数据。

我遇到的问题是我无法在视图支持表上有INSERT INTO people (fullname, gender) VALUES ("James Jones", "male"); 约束,否则会出现如下查询:

created_at
由于NEW.create_at上的约束,

会失败,因为触发器功能中的NULL显然是NON NULL

所以我的问题是: 有没有人知道在可更新视图中处理IF NEW.created_at IS NULL THEN INSERT INTO parties VALUES (NEW.id, NEW.party_type_id, NEW.fullname); ELSE INSERT INTO parties VALUES (NEW.id, NEW.party_type_id, NEW.fullname, NEW.created_at); END IF; 约束的方法,而不需要采取类似的方法:

  ALTER TABLE people
  ALTER COLUMN created_at SET DEFAULT now()

虽然该解决方案适用于单个列,但如果有更多解决方案,那么解决方案会非常快速地变得非常混乱。

修改

最后,我实施了 Mad Scientist 推荐的解决方案。对于任何可能在将来偶然发现这个问题的人,我的最终解决方案是:

NEW

在视图触发器中的这种方式我只需要在相应的表中设置值,因为 people 视图将负责使用默认值填充NULL变量,其中{ {1}}通常是。

2 个答案:

答案 0 :(得分:2)

您可以在视图上创建默认值,而不仅仅在表格上创建默认值。如果你有一个可更新的视图,我只会将基础表中的默认值添加到它。 NOT NULL约束可以由基础表强制执行,但如果没有提供值,则INSTEAD OF触发器将看到默认值,而不是有问题的NULL。

视图上的默认值的语法与更改表的默认值相同。

答案 1 :(得分:1)

你可以这样做:

IF NEW.created_at IS NULL THEN
    NEW.created_at = now() ;
END IF ;
/* Do the same for all columns requiring default values */

INSERT INTO 
       parties 
       (id,     party_type_id,     fullname,     created_at)
VALUES 
       (NEW.id, NEW.party_type_id, NEW.fullname, NEW.created_at);

INSERT INTO 
       parties 
       (id,     party_type_id,     fullname,     created_at)
VALUES 
       (NEW.id, NEW.party_type_id, NEW.fullname, coalesce(NEW.created_at, now()));

检查https://ffmpeg.zeranoe.com/