有些视图是可更新的,对它们的引用可用于在数据更改语句中指定要更新的表。也就是说,你可以在这样的语句中使用它们更新
,删除
,或插入
来更新基础表的内容。派生表和公共表表达式也可以在多表中指定更新
而且删除
语句,但只能用于读取数据以指定要更新或删除的行。通常,视图引用必须是可更新的,这意味着它们可以被合并而不被物化。复合视图有更复杂的规则。
要使视图可更新,视图中的行与底层表中的行之间必须存在一对一的关系。还有一些其他的构造使视图不可更新。更具体地说,如果视图包含以下任何一个,则不可更新:
视图中生成的列被认为是可更新的,因为可以给它赋值。但是,如果显式更新了这样的列,则惟一允许的值为默认的
.有关已生成列的信息,请参见第13.1.20.8节“创建表和生成的列”.
方法可以对多表视图进行处理,那么它有时可能是可更新的合并
算法。为此,视图必须使用内部连接(而不是外部连接或联盟
).此外,只能更新视图定义中的单个表,因此集
子句必须只命名视图中一个表的列。视图使用UNION ALL
是不允许的,尽管理论上它们可能是可更新的。
关于可插入性(可以用插入
语句),一个可更新的视图是可插入的,如果它也满足这些额外的视图列的要求:
视图列名不能重复。
视图必须包含基表中没有默认值的所有列。
视图列必须是简单的列引用。它们不能是这样的表达:
3.14159 col1 + 3 UPPER(col2) col3 / col4 (子查询)
MySQL设置了一个标志,称为视图更新标志创建视图
时间。旗帜设置为是的
(真正的)如果更新
而且删除
(以及类似的操作)对于视图是合法的。否则,将标志设置为没有
(假)。的IS_UPDATABLE
列中的INFORMATION_SCHEMA。的观点
表显示此标志的状态。这意味着服务器总是知道视图是否可更新。
如果一个视图是不可更新的,语句更新
,删除
,插入
是非法的,并且被拒绝。(即使视图是可更新的,也可能无法插入到其中,如本节其他部分所述。)
的值可能会影响视图的可更新性updatable_views_with_limit
系统变量。看到第5.1.8节,“服务器系统变量”.
对于下面的讨论,假设这些表和视图存在:
CREATE TABLE t1 (x INTEGER);CREATE TABLE t2 (c INTEGER);CREATE VIEW vmat AS SELECT (x) AS s FROM t1;CREATE VIEW vup AS SELECT * FROM t2;CREATE VIEW vjoin AS SELECT * FROM vmat JOIN vup ON vmat.s=vup.c;
插入
:对象的插入表插入
语句可以是被合并的视图引用。如果视图是连接视图,则视图的所有组件都必须是可更新的(不是物化的)。对于多表可更新视图,插入
如果它插入到单个表中,则可以工作。该语句无效,因为连接视图的一个组件是不可更新的:
INSERT INTO vjoin (c) VALUES (1);
这种说法是有效的;视图不包含物化组件:
INSERT INTO vup (c) VALUES (1);
更新
中要更新的一个或多个表更新
语句可以是被合并的视图引用。如果视图是连接视图,则视图的至少一个组件必须是可更新的(这与插入
).在多重表中
更新
语句时,语句的更新表引用必须是基表或可更新视图引用。非更新的表引用可以是物化视图或派生表。这种说法是有效的;列
c
来自连接视图的可更新部分:UPDATE vjoin SET c=c+1;
这个陈述是无效的;列
x
来自不可更新部分:UPDATE vjoin SET x=x+1
这种说法是有效的;多表的更新表引用
更新
是一个可更新的视图(vup
):更新vup JOIN (SELECT SUM(x) AS s FROM t1) AS dt ON…集c = c + 1;
这个陈述是无效的;它尝试更新一个物化的派生表:
更新vup JOIN (SELECT SUM(x) AS s FROM t1) AS dt ON…集合s = s + 1;
删除
中要删除的一个或多个表删除
语句必须是合并视图。不允许连接视图(这与插入
而且更新
).该语句无效,因为视图是一个连接视图:
删除vjoin WHERE…;
这个语句是有效的,因为视图是一个合并的(可更新的)视图:
删除vup WHERE…;
这个语句是有效的,因为它从一个合并的(可更新的)视图中删除:
DELETE vup FROM vup JOIN (SELECT SUM(x) AS s FROM t1) AS dt ON…;
下面是更多的讨论和示例。
本节前面的讨论指出,如果不是所有列都是简单列引用(例如,如果视图包含表达式或复合表达式的列),则视图是不可插入的。尽管这样的视图是不可插入的,但如果只更新非表达式的列,则可以更新它。考虑一下这个观点:
CREATE VIEW v AS SELECT col1, 1 AS col2 FROM t;
此视图不可插入,因为col2
是一个表达式。但如果更新不尝试更新,则它是可更新的col2
.此更新是允许的:
SET col1 = 0;
此更新是不允许的,因为它试图更新表达式列:
SET col2 = 0;
如果表中包含AUTO_INCREMENT
属性的表上的可插入视图AUTO_INCREMENT
的值不变LAST_INSERT_ID ()
,因为将默认值插入到不是视图一部分的列的副作用不应该是可见的。