4.2.4 视图更新
尽管对查询而言,视图是一个有用的工具,但如果我们用它们来表达更新
、插入
或删除
,它们可能带来严重的问题。困难在于,用视图表达的数据库修改必须被翻译为对数据库逻辑模型中实际关系的修改。
向视图插入数据
更新一个表上的的视图的情况
假设我们此前所见的视图faculty
被提供给一个职员。既然我们允许视图名出现在任何关系名可以出现的地方,该职员可以这样写出:
1 | insert into faculty |
这个插入必须表示为对instructor
关系的插入,因为instructor
是数据库系统用于构造视图faculty
的实际关系。然而,为了把一个元组插入到instructor
中,我们必须给出salary
的值。存在两种合理的解决方法来处理该插入:
- 拒绝插入,并向用户返回一个错误信息。
- 向
instructor
关系插入元组('30765','Green', 'Music',null)
1 | mysql> insert into faculty |
1 | | 30765 | Green | Music | NULL | |
更新多个表上的视图的情况
通过视图修改数据库的另一类问题发生在这样的视图上:
1 | create view instructor_info |
这个视图列出了大学里每个教师的ID
、name
和建筑名
。
考虑如下通过该视图的插入:
1 | insert into instructor_info |
假设没有标识为69987
的教师,也没有位于Taylor
大楼的系。那么向instructor
和department
关系中插入元组的唯一可能的方法是:
- 向
instructor
中插入元组('69987','White',null,null)
- 并向
department
中插入元组('null','Taylor',null)
。
但是这个更新并没有产生出所需的结果,因为视图关系instructor_info
中仍然不包含元组('69987','White','Taylor')
,
1 | mysql> insert into instructor_info |
因此,通过利用空值来更新 instructor
和department
关系以得到对instructor_info
所需的更新是不可行的。
一般不允许对视图关系进行修改
由于如上所述的种种问题,除了一些有限的情况之外,一般不允许对视图关系进行修改。
不同的数据库系统指定了不同的条件以允许更新视图关系;请参考数据库系统手册以获得详细信息。通过视图进行数据库修改的通用问题已经成为重要的研究课题,文献注解中引用了一些这方面的研究。
可更新的视图要满足的条件
一般说来,如果定义视图的查询
对下列条件都
能满足我们称SQL
视图是可更新的(updatable
)(即视图上可以执行插入
、更新
或删除
from
子句中只有一个数据库关系。select
子句中只包含关系的属性名,不包含任何表达式
、聚集
或distinct
声明。- 任何没有出现在
select
子句中的属性可以取空值;即这些属性上没有not null
约束,也不构成主码的部分。 - 查询中不含有
group by
或having
子句。
实例 可更新的视图
在这些限制下,下面的视图上允许执行update
、 insert
和delete
操作:
1 | create view history_instructors |
可更新的视图存在的问题
即便是在可更新的情况下,下面这些问题仍然存在。假设一个用户尝试向视图history_instructors
中插入元组('25566','Brown','Biology',100000)
:
1 | insert into history_instructors |
这个元组可以被插入到instructor
关系中,但是由于它不满足视图所要求的选择条件,它不会出现在视图history_instructors
中。
1 | mysql> insert into history_instructors |
1 | mysql> select * from history_instructors; |
拒绝向视图插入一条不满足视图的where
子句条件的元组
在默认情况下,SQL
允许执行上述更新。但是,可以通过在视图定义的末尾包含with check option
子句的方式来定义视图。
这样,如果向视图中插入
(insert
)一条不满足视图的where
子句条件的元组,数据库系统将拒绝
该插入
操作。
类似地,如果更新
的新值不满足where
子句的条件,更新
(update
)也会被拒绝。
SQL:1999对视图更新的规则
SQL:1999
对于何时可以在视图上执行插入、更新和删除有更复杂的规则集,该规则集允许通过类更大视图进行更新,但是这些规则过于复杂,我们就不在这里讨论了
原文链接: 4.2.4 视图更新