视图是从一个或多个表(或视图)导出的虚表,DBMS仅在数据字典中存放视图的定义,而视图的数据仍然实际存储于导出它的基表中
Tutorial D中定义视图的基本语句如下:
VAR <view_name> VIEW (<relational_condition>) {<property_list>};
那么视图有什么作用呢?
C.J.Date从形式化的角度来定义视图的两种操作:检索(Retrieval)和更新(Update)
定义在数据库(表)D上执行操作X得到视图V,即V=X(D)
,则对V视图进行检索就是R(V)=R(X(D))=X‘(D)
,也就是说对视图检索相当于对它的基表检索
需要注意的是如果V=X(D)
被实现(Materializing)了,那么X(D)就是是基本表的一份拷贝,对V的操作和D独立开来;如果V=X(D)
只是一个虚表,那么对V的操作会直接修改基本表D(大多数DBMS是采取后种方案)
如果定义U为更新操作,那么U(V)=U(X(D))
,但是我们可以发现U(X(D))
和X(U‘(D))
并不能等价,原因就是V的定义操作X可能涉及集合操作UNION或者from从句的JOIN等复杂操作,此时Update操作对于基本表来说存在歧义,是无法执行的
比如说V=A UNION B
,去update一个元组到底是更新基表A中的元组还是更新基表B中的元组还是AB同时更新;又比如说去insert一个元组不满足B的完整性约束但满足A的完整性约束,是只插入A还是整个插入操作失败
PPT和书上有很多例子来阐述这个问题,我们需要掌握的核心就是对视图的更新操作存在某些限制,不是所有视图都能够更新
SQL中定义一个视图的语法如下:
create view <view_name> as <query expression>;
query expression可以是任何合法的select查询表达式,如定义一个“好供应商”视图:
create view good_supplier
as select S.s#, S.status, S.city
from S
where s.status > 15;
query expression也可以有聚合函数、集合操作等等,SQL定义View还支持在View后面跟上属性list作为属性名(当然也可以用select as做重命名实现),如为各部门的员工销售额统计创建一个视图:
create view dept_summary(name, minsal, maxsal, avgsal)
as select dname, min(sal), max(sal), avg(sal)
from EMP, DEPT
where DEPT.d# = EMP.d#
group by dname;
对视图检索的语法和对表检索是一样的,都用select语句,如:
select name from dept_summary where avgsal > 2000;
这句话等价于对基表进行如下检索:
select dname as name from EMP, DEPT
where EMP.d# = DEPT.d#
group by dame having avg(sal) > 2000;
大多数SQL的实现(Oracle、MySQL等)支持对单一关系上的简单视图做更新操作,简单视图是如下的视图:
注:这里所说的视图更新包含了update、insert、delete三个操作
但是我们发现即使是对单一关系上的简单视图做更新操作,也会出现问题,如在好供应商表中update某个供应商的status值:
update good_supplier set status = 10 where S# = ‘s1‘;
DBMS翻译成
update S set status = 10 where status > 15 and S# = ‘s1‘;
执行,而视图good_supplier的定义并没更改,那么执行了这句话供应商s1虽然在基础表中的status值变成10了,但是该供应商s1却再也不属于good_supplier了,逻辑上出错(更新了视图却直接删掉了元组)
SQL为了防止上述情况的发生,支持在视图定义时插入with check option
后缀进行检查上述类似的逻辑错误,如果好供应商有如下定义:
create view good_supplier
as select S.s#, S.status, S.city
from S
where s.status > 15
with check option;
那么如上所述产生逻辑错误的update语句便不满足检查条件,DBMS会通知用户执行失败
原文地址:http://blog.csdn.net/u014030117/article/details/46483483