我正在使用postgres9.1,我一直在努力寻找有关如何创建视图的教程,以后可以更新并在视图中插入新行。
有人可以给我一些关于如何进行可更新的视图并可以接受插入新行的指导吗?
答案 0 :(得分:2)
可更新视图有点复杂。有两种方法可以做到这一点,一种是使用RULE,另一种是使用TRIGGER。触发器会带来更多性能问题,而规则会带来更微妙的编码问题。我将在这里介绍这两种方法。
假设我有一个基表和一个视图,它提供对基表的一部分的访问:
CREATE TABLE mybase (
id serial primary key,
type_id int not null,
payload text not null
);
CREATE VIEW type1 AS select * from mybase WHERE type_id = 1;
好的,够简单。现在我们想让视图更新。旧方法(维护问题)是使用规则:
CREATE RULE on_insert AS ON insert TO type1
DO INSTEAD INSERT into mybase(id, type_id, payload) VALUES (new.id, 1, payload);
CREATE RULE on_update AS ON update TO type1
DO INSTEAD UPDATE mybase set payload = new.payload where id = old.id;
现在这可行,但有几点需要注意。首先是如果我:
INSERT INTO type1 (id, type_id, payload) values (DEFAULT, 2, 'foo');
它将默默地输入1而不是2.这可能是不可取的。您可以使代码更复杂,或者可以调用函数来执行插入和更新,但RULEs的优点是可以在计划时解析为查询,并且函数将每行运行一次,因此更新可以更新一百万使用简单的规则而不是函数,行将更好地执行FAR。正确地获取规则是复杂而棘手的,但这意味着对视图的更新将按照写入基表更新的方式进行扩展。
如果您有多个表,但事情变得复杂得多,因为您有更新或删除多个行,并且因为它在计划时间(而不是每行)合并,一方可能会被删除,然后另一方可能不会能够找到需要删除的内容。但是如果你去了函数,那么你就会在删除和更新时写出扩展问题(这基本上会把你绑定到重复的索引扫描循环中)。
另一种选择是使用触发器。触发器是为每个被写入的行调用的函数,因此它们具有调用函数的规则的写入缩放问题。通过这种方法,我们可以在视图上创建触发器函数并创建触发器:
CREATE OR REPLACE FUNCTION type1_trigger_func() RETURNS trigger LANGUAGE PLPGSQL AS
$$
BEGIN
IF TG_OP = 'INSERT' THEN
IF new.type_id <> 1 THEN RAISE EXCEPTION 'Invalid type!'; END IF;
insert into mybasetable (id, type_id, payload)
VALUES (new.id, new.type_id, new.payload);
RETURN NEW;
ELSIF TG_OP = 'UPDATE' THEN
IF new.type_id <> 1 THEN RAISE EXCEPTION 'Invalid type!'; END IF;
-- update statement goes here
RETURN NEW;
ELSIF TG_IP = 'DELETE' THEN
DELETE FROM mybasetable WHERE id = old.id;
RETURN OLD;
END IF;
END;
$$;
然后我们创建触发器:
CREATE TRIGGER make_updateable INSTEAD OF INSERT OR UPDATE OR DELETE ON TYPE1
FOR EACH ROW EXECUTE PROCEDURE type1_trigger_func();
一般来说,RULE和TRIGGER在这种情况下的困难使我倾向于存储过程而不是视图。
答案 1 :(得分:1)
使用视图更新数据 视图可用于更新数据的查询,但受一些限制。请记住,视图不是表并且不包含数据 - 实际修改始终在表级别进行。视图不能用作覆盖基表中定义的任何约束,规则或参照完整性的机制。
通过视图更新数据的限制 您可以在视图中插入,更新和删除行,但受以下限制:
如果视图包含多个表之间的连接,则只能在视图中插入和更新一个表,并且不能删除行。
您无法根据联合查询直接修改视图中的数据。您无法修改使用GROUP BY或DISTINCT语句的视图中的数据。
正在修改的所有列都受到与直接针对基表执行语句相同的限制。
无法通过视图修改文字和图片列。