我的网站是使用运行在 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
查询有效。 UPDATE
、INSERT
和 DELETE
命令不起作用;他们因上述错误而失败。
这是权限问题吗?语法错误?还有别的吗?
PostgreSQL 视图默认不可更新。您必须告诉 PostgreSQL 您希望如何更新视图。
使用“无条件
ON UPDATE DO INSTEAD
规则”(如您粘贴的错误消息所述)执行此操作,或者最好在 PostgreSQL 9.1 及更高版本上使用视图触发器。我在我对您上一篇文章的回答中提供了所有内容的链接,但这里有更多信息:
INSTEAD OF
触发器更新视图CREATE TRIGGER
CREATE VIEW
在许多情况下,最好将视图保留为只读并仅更新基础表。由于您没有提供视图的定义,因此很难说出它实际上涉及什么。使用在
\d uac_institution_view
中运行 psql
的输出更新您的问题,并评论说您已经这样做了;也许我可以指出一种直接在基础表上运行更新的方法。
您使用的是非常过时的 PostgreSQL 版本 (8.3),因此您无法使用首选的
INSTEAD OF
触发器方法,您必须使用规则或直接更新基础表。
仅供参考,在发布涉及规则/触发器的答案后,PostgreSQL 9.3 推出了自动更新视图。截至 2013 年 6 月 27 日,9.3 版本处于 beta 2 阶段,因此尚未正式发布。
我使用的是 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
正如 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 版本。
如果您认为有
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 文档中所述)自动更新视图将比手动创建规则更快。
您可以对视图进行
INSERT
、UPDATE
和 DELETE
操作。
例如,您创建
person
表,如下所示:
CREATE TABLE person (
id INTEGER,
first_name VARCHAR(20),
last_name VARCHAR(20),
age INTEGER
);
然后,将 2 行插入到
person
表中,如下所示:
INSERT INTO person (id, first_name, last_name, age)
VALUES (1, 'John', 'Smith', 27), (2, 'David', 'Miller', 32);
然后,您创建
my_view
视图,如下所示:
CREATE VIEW my_view AS
SELECT first_name, age FROM person;
然后调用
my_view
得到如下所示的结果。 *id
和last_name
不可用:
postgres=# SELECT * FROM my_view;
first_name | age
------------+-----
John | 27
David | 32
(2 rows)
现在,您可以使用
person
向 my_view
表插入 2 行,如下所示。 *id
和last_name
不可用:
INSERT INTO my_view (first_name, age)
VALUES ('Robert', 18), ('Mark', 40);
然后,将 2 行插入到
person
表中,如下所示:
postgres=# SELECT * FROM person;
id | first_name | last_name | age
----+------------+-----------+-----
1 | John | Smith | 27
2 | David | Miller | 32
| Robert | | 18
| Mark | | 40
(4 rows)
并且,您可以使用
person
更新 my_view
表,如下所示。 *id
和last_name
不可用:
UPDATE my_view SET first_name = 'Tom' WHERE age = 32;
然后,
person
表更新如下:
postgres=# SELECT * FROM person;
id | first_name | last_name | age
----+------------+-----------+-----
1 | John | Smith | 27
| Robert | | 18
| Mark | | 40
2 | Tom | Miller | 32
(4 rows)
并且,您可以使用
person
从 my_view
表中删除 2 行,如下所示。 *id
和last_name
不可用:
DELETE FROM my_view WHERE age = 18 OR age = 40;
然后,从
person
表中删除2行,如下所示:
postgres=# SELECT * FROM person;
id | first_name | last_name | age
----+------------+-----------+-----
1 | John | Smith | 27
2 | Tom | Miller | 32
(2 rows)