1.6.3 复杂视图

以前在创建视图时,在CREATE VIEW语句的SELECT子句中只涉及一个表的操作,并且只是对基表中的列进行简单的查询,并没有出现多个基表,或者对基表中的列进行表达式运算或者函数运算的情况,这种视图被称为简单视图。对简单视图不仅可以进行查询操作,还可以进行DML操作。

复杂视图是这样的视图,视图中的列是从基表中的列经过表达式或函数运算而来,或者是对基表进行了DISTINCT查询,或者涉及多个表的操作。总而言之,如果在用CREATE VIEW语句创建视图时,在SELECT之后的列名中使用了表达式、函数,或者使用了DISTINCT关键字,或者对多个表进行了连接查询,这样的视图都是复杂视图。

创建复杂视图仍然是通过执行CREATE VIEW命令完成的,只不过因为在SELECT子句中使用了表达式或者函数,这样的运算式不能作为视图中的列名,所以在创建复杂视图时必须为每个列指定列名。例如,下面的语句创建视图view_3:


SQL>CREATE OR REPLACE VIEW view_3(deptno, max_sal, min_sal, sum_sal)AS

SELECT deptno, max(sal),min(sal),sum(sal)

FROM emp

GROUP BY deptno;


视图view_3中的max_sal、min_sal和sum_sal三个列是通过对基表中的列SAL分别经过三个函数的运算而来的,所以必须为这三个列明确地指定列名。

下面的语句用来创建视图view_4,这个视图涉及两个表的操作,并且对其中的一个列进行了表达式运算。


SQL>CREATE OR REPLACE VIEW view_4(empno, ename, dname, sal, comm)AS

SELECT empno, ename, dname, sal*1.1,comm

FROM emp, dept

WHERE emp.deptno=dept.deptno;


对复杂视图,允许的操作只有查询,大部分视图不允许DML操作。例如,如果通过下面的INSERT语句向视图view_4中插入一行,系统将出错。


SQL>INSERT INTO view_4 VALUES(9999,'Kate',10,2000,200);


相应的错误信息为:


ORA-01776:无法通过连接视图修改多个基表


现在我们总结一下在什么样的视图上可以执行DML操作,在什么样的视图不允许执行DML操作。

对于简单视图,如果基表中的所有列都被包含在视图中,或者至少主键列和所有不允许为空的列都被包含在视图中,并且在创建视图的CREATE VIEW语句的SELECT语句中最多只使用了WHERE子句,对这样的视图是可以进行插入、删除、修改操作的。如果在创建这样的简单视图时使用了WITH CHECK OPTION选项,那么执行DML操作时要遵守一定的约束条件。

对于涉及多个基表的复杂视图,如果其中至少一个表的所有列都被包含在视图中,或者至少一个表的主键列和所有不允许为空的列都被包含在视图中,并且在创建视图的CREATE VIEW语句的SELECT语句中最多只使用了WHERE子句,这样的视图是允许进行插入、删除、修改操作的。对这样的视图进行DML操作时,只有其中一个表可以被修改,并且被修改的列只能映射到一个表中。

对于只涉及一个基表的复杂视图,如果视图中的列是对基表的列经过某种运算而来,包括表达式、AVG等函数,或者在创建视图的CREATE VIEW语句的SELECT语句中使用了DISTINCT关键字、GROUP子句,对这样的视图是不能进行DML操作的。

对于涉及多个表的视图,如果视图中的列没有包含其中一个表中的所有主键列和所有不为空的列,或者视图中的部分列是经过对基表中的列经过某种运算而来的,或者在创建视图时在SELECT子句中使用了DISTINCT关键字、GROUP子句,这样的视图也是不能进行DML操作的。