在我的测试应用程序中,我在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}}通常是。
答案 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()));