浅谈视图(Views)
浅谈视图(Views) 作者:齐相峰
视图提供了从一个表或多个表查看数据的方式。
视图实际上是一个对结果数据集的命名。它是一个SELECT语句,只要视图被引用,它就会执行。因此,视图可以被认为和物理基础表(base table)一样拥有列和行。对于取出数据,视图可以像其他基础表一样被使用。视图是否可以被执行insert、update、delete操作,取决于它的定义。
在不同的数据库中,视图的机制是不同的,区别主要是视图是否可以被更新操作。以下是对DB2和Oracle数据库中的视图作简单的介绍。
一. DB2
当视图中的列直接来自于基础表中的列,那些列也就继承了基础表中所有约束。例如视图包含基础表中的一个外键,对视图进行新增和修改操作会像基础表一样受到参照约束的限制。同样,如果基础表是一个父表,对视图的修改和删除操作服从与基础表的修改、删除同样的规则。
视图的性质:
可删除视图(Deletable views): 如果以下条件都成立则试图就是可删除的:
外层选择的每一个FROM 子句,只能包含一个基表(不包含OUTER子句)、可删除的视图(不包含OUTER子句)、可删除的嵌套表表达式或者可删除的一般表表达式。(不能指定别名)
外层选择语句不包括VALUES子句
外层选择语句不包括GROUP BY或者HAVING子句
外层选择语句在选择的列中不能包含列的函数。
外层选择语句不包含SET操作(UNION, EXCEPT or INTERSECT) UNION ALL 除外。
UNION ALL的所有操作对象中的基础表不能是同一个表,并且每一个基础表必须都是可以删除的。
外层选择语句选择的列表不能使用DISTINCT。
可更新视图(Updatable views): 如果满足所有下列条件,视图的列是可更新的:
视图是可删除的
视图的列决定了基表的列(没有使用dereference operation)并且没有指定READ ONLY选项
如果视图包括UNION ALL语句,则UNION ALL操作的所有相对应的列,都有严格的类型匹配,(包括长度或精度等级)并且有完全匹配的默认值。
如果视图中所有的列是可更新的,则试图是可更新的。
可新增视图(Insertable views):
如果视图是可更新的,并且视图的选择语句不包括UNION ALL语句,则视图是可新增的。
只读视图(Read-only views):不是可删除的视图,就是只读视图。
二. Oracle
在Oracle中,当你创建的视图来源于多个基础表或视图时,这样的视图叫做连接视图Join Views。
例如如下语句创建的视图就是Join View。
CREATE VIEW division1_staff AS
SELECT ename, empno, job, dname
FROM emp, dept
WHERE emp.deptno IN (10, 30)
AND emp.deptno = dept.deptno;
如果一个join view允许进行UPDATE、 INSERT和DELETE操作,这样的视图叫做可更新的连接视图updatable join view。
updatable join view是在最外层select语句的from子句中包括一个以上的表,并且没有用WITH READ ONLY 子句进行限制。
updatable join views的规则如下:
规则
描述
通用规则
任何对join view的INSERT、UPDATE或DELETE操作,一次只能修改一个基础表
UPDATE规则
join view中所有被修改的列,必须可以对应到一个key-preserved table中的列。 如果视图定义的时候使用了WITH CHECK OPTION子句,则所有连接的列和重复出现的表中的列都是不可修改的。
DELETE 规则
当join view有且只有一个key-preserved table时,才可以被删除操作。如果视图定义使用了WITH CHECK OPTION子句,并且key preserved table重复出现,则视图中的数据行是不能被删除的。
INSERT 规则
INSERT语句不能显式或隐式的涉及nonkey preserved table中的列。 如果join view定义时使用了WITH CHECK OPTION子句,则INSERT操作是不允许的。
key-preserved table: 表中每一个key同时也是join的结果集的key,那么这个表叫做key-preserved,因为他的Keys通过join后被保留下来了。
key-preserving的特性不是根据视图的实际结果数据决定的,而是由视图和基础表的物理结构决定的。
以上描述的是视图被创建的时候具有的inherently modifiable特性。对于复杂的view,如果不能用DML语句(insert、update、delete)直接更改,还可以用INSTEAD OF triggers进行显式的更改。这些triggers叫做INSTEAD OF triggers,因为不像其他类型的triggers,Oracle执行trigger来代替执行出发trigger的语句。这些trigger必须定义如何直接对基础表进行UPDATE、INSERT 或 DELETE操作。
你可以正常的对视图进行UPDATE、INSERT和DELETE操作,INSTEAD OF trigger会在后台运行,保证对基础表的正确处理。INSTEAD OF triggers只能定义为每一行触发。
由此可见,对于视图的更新机制,在不同的数据库中有很大的不同。我们在数据库设计的时候,可以根据不同的数据库灵活的使用视图,但是相伴而来的一个问题就是在系统在不同数据库之间进行移植的时候会增大工作量。