0

我正在使用 postgres9.1,我一直在努力寻找一些关于如何创建可以稍后更新的视图以及可以在视图中插入新行的教程。

有人能给我一些关于如何做一个可更新的视图并且可以接受插入新行的指导吗?

4

2 回答 2

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。这可能是不可取的。您可以使您的代码更复杂,或者您可以调用一个函数来执行您的插入和更新,但 RULE 具有在计划时被解析为查询的优点,并且函数将每行运行一次,因此更新一百万使用简单规则的行将比使用函数执行得更好。获得正确的规则是复杂和棘手的,但这意味着对视图的更新将以写入基表更新的方式扩大。

如果您有多个表,但是事情会变得更加复杂,因为您已经更新或删除了多行,并且因为这在计划时间(而不是每行)被合并,一侧可能会被删除,然后另一侧可能无法找到需要删除的内容。但是,如果您使用函数,那么您会遇到与删除和更新有关的扩展问题(这基本上会将您束缚在重复的索引扫描循环中)。

另一种选择是使用触发器。触发器是为正在写入的每一行调用的函数,因此它们具有规则调用函数的写入缩放问题。使用这种方法,我们将创建触发器函数并在视图上创建触发器:

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 的困难使我倾向于存储过程而不是视图。

于 2013-03-10T15:31:54.617 回答
1

使用视图更新数据 视图可用于更新数据的查询,但有一些限制。请记住,视图不是表并且不包含数据——实际的修改总是发生在表级别。视图不能用作覆盖基表中定义的任何约束、规则或引用完整性的机制。

通过视图更新数据的限制 您可以在视图中插入、更新和删除行,但受到以下限制:

如果视图包含多个表之间的连接,则只能在视图中插入和更新一个表,不能删除行。

您不能根据联合查询直接修改视图中的数据。您不能修改使用 GROUP BY 或 DISTINCT 语句的视图中的数据。

所有被修改的列都受到相同的限制,就好像直接对基表执行语句一样。

无法通过视图修改文本和图像列。

于 2014-07-11T12:30:23.390 回答