11

我的网站是使用在 Ubuntu 11.10 上的 Postgresql 8.3 服务器上运行的 Drupal 6 开发的。还有 webmin 版本 1.590。

现在我想更新表中的记录,但是当我运行时:

UPDATE uac_institution_view SET status = '2' WHERE nid = '9950'

它给了我一个错误,例如:

执行 SQL 失败:SQL UPDATE uac_institution_view SET status = '2' WHERE nid = '9950' 失败:错误:无法更新视图 提示:您需要一个无条件的 ON UPDATE DO INSTEAD 规则。

问题是只有SELECT查询有效。UPDATEINSERT并且DELETE命令不起作用;他们因上述错误而失败。

这是权限问题吗?语法错误?还有什么?

4

4 回答 4

25

默认情况下,PostgreSQL 视图不可更新。您必须告诉 PostgreSQL 您希望如何更新视图。

使用“无条件ON UPDATE DO INSTEAD规则”(如您粘贴的错误消息所述)或最好在 PostgreSQL 9.1 及更高版本上使用视图触发器执行此操作。我在对您之前的帖子的回答中提供了所有这些内容的链接,但这里有更多信息:

在许多情况下,最好将视图保留为只读并仅更新基础表。由于您没有提供视图的定义,因此很难说这实际上会涉及什么。\d uac_institution_view使用运行的输出更新您的问题psql并评论说您已经这样做了;也许我可以指出一种直接在基础表上运行更新的方法。

您使用的是非常过时的 PostgreSQL (8.3) 版本,因此您不能使用首选INSTEAD OF触发器方法,您必须使用规则或直接更新基础表。

于 2012-10-31T05:14:54.477 回答
8

仅供参考,在发布涉及规则/触发器的答案后,PostgreSQL 9.3 推出了自动更新视图。9.3 版在 2013 年 6 月 27 日处于 beta 2 中,所以它还不是 GA。

这是一个示例:https ://web.archive.org/web/20160322164044/http://michael.otacoo.com/postgresql-2/postgres-9-3-feature-highlight-auto-updatable-views/

于 2013-08-19T22:09:13.463 回答
4

我在 postgres 9.5 上,默认情况下视图是可更新的。例子 :

CREATE TABLE UP_DATE (id number, name varchar2(29));
insert into up_date values(1, 'Foo');
select * from up_date;
CREATE OR REPLACE VIEW UPDATE
AS
Select 
name from up_date;
select * from update;
insert into update values('Bar');
select * from update;

将推出 Foo 和 Bar

于 2016-10-03T04:23:52.893 回答
0

正如 Jeff French 所指出的,一切都从 PG 9.3 开始工作......除了一些例外(下面的更多信息)。

简单的例子

您可以在 PostgreSQL 上测试此代码。完成后使用级联删除(使用表格删除视图)。

-- create table
--DROP TABLE user_table CASCADE;
CREATE TABLE user_table (
    id serial,
    lastname varchar(100),
    user_type varchar(2) DEFAULT 'nn',
    PRIMARY KEY (id)
);
-- initial data
INSERT INTO user_table(lastname) VALUES('Foo');
SELECT * FROM user_table;

-- simple view (note, no id here)
CREATE OR REPLACE VIEW user_view
AS
    SELECT lastname, user_type 
    FROM user_table
;

-- check view (will have initial data)
SELECT * FROM user_view;

-- insert into user_table via view
INSERT INTO user_view VALUES('Bar');
-- check (both will have both records)
SELECT * FROM user_view;
SELECT * FROM user_table;
-- you can run above many times
-- (id will auto-increment even though it is not in the view)

-- update user_table via view
UPDATE user_view SET user_type='v' WHERE lastname = 'Bar';
SELECT * FROM user_table;

限制

不过有一些限制,这取决于你的 PG 版本。

  • PG 9.3 视图中不能有任何表达式等。也只允许一个表......所以或多或少是一个简单的选择限制、重新排序或重命名列。
  • PG 9.4 中,视图可以部分更新。所以你可以有表达,但你不能更新它们(至少不是开箱即用的)。

如果你有WHERE你的观点,那么你可能会得到一些奇怪的结果。所以这仍然适用于插入:

CREATE OR REPLACE VIEW user_view
AS
    SELECT lastname as last_name, user_type
    FROM user_table
    WHERE user_type = 'v'
;
INSERT INTO user_view VALUES('Bar');

但更新可能不起作用。至少这不起作用,因为它将更新 0 行:

UPDATE user_view SET user_type='v';

因为实际上这将等同于以下查询(如果您考虑一下,这很有意义):

UPDATE user_view SET user_type='v' WHERE user_type = 'v';

我想知道他们是否会在某个时候支持联接...但是在撰写本文时,PG 14 已经发布,并且它不支持在视图中加入表格(我的意思是更新)。

备择方案

您仍然可以使用INSTEAD OF触发器,尤其是对于更复杂的视图。而且您可以使用规则...但是(如CREATE RULE 文档中所述)自动更新的视图将比手动创建的规则更快。

于 2021-10-19T23:10:54.127 回答