1.6 视图
视图是一种非常重要的数据库对象,它的形式类似于普通表,我们可以从视图中查询数据。实际上它是建立在表上的一种虚表,在视图中并不存储真正的数据,而是仅仅保存一条SELECT语句,对视图的访问将被转化为对表的访问。视图所基于的表称为基表,而视图可以认为是对基表的一种查询操作。
使用视图的主要目的是为了方便用户访问基表,以及保证用户对基表的安全访问。
对用户而言,往往要对一个表进行大量的查询操作,如果查询操作比较复杂,并且需要频繁地进行,那么可以为这个查询定义一个视图。假设用户需要经常执行下面的查询:
SELECT dname FROM dept
WHERE deptno=(SELECT deptno FROM emp a
GROUP BY deptno
HAVING avg(sal)>all(SELECT avg(sal)FROM emp
WHERE deptno!=a.deptno GROUP BY deptno))
如果为这个查询定义一个视图,那么用户只要执行一条简单的SELECT语句,对这个视图进行查询,那么实际的操作就是对基表dept执行了上面的查询。
需要注意的是,在视图中并不保存对基表的查询结果,而仅仅保存一条SELECT语句。只有当访问视图时,数据库服务器才去执行视图中的SELECT语句,从基表中查询数据。虽然我们对视图没有做过任何修改,但是对视图的多次访问可能得到不同的结果,因为基表中的数据可能随时被修改。所以视图中并不存储静态的数据,而是从基表中动态查询的。
从另外一个角度来看,视图可以保证对基表的安全访问。在设计表时,我们一般是从整体的角度来考虑表的结构的,而不是从每个用户的角度来确定表结构以及定义允许的操作。对于同一个表,不同的用户可以进行不同的操作,可以访问不同的数据。这样我们就可以为不同的用户定义不同的视图,从而保证用户只能进行允许的操作,访问特定的数据。
例如,对于员工表emp,公司经理可以浏览所有的数据,但是不能修改数据;人事部门可以查看和修改员工的职务、部门等信息,也可以增加一个新员工;财务部门可以查看、修改员工的工资和奖金;而对于普通员工,只能查看其他员工的部门和职务等信息。如果为每一类用户分别定义一个视图,就可以保证他们对同样的数据进行不同的访问。
1.6.1 视图的创建、修改和删除
用户可以在自己的模式中创建视图,只要具有CREATE VIEW这个系统权限即可。如果希望在其他用户的模式中创建视图,则需要具有CREATE ANY VIEW系统权限。如果一个视图的基表是其他用户模式中的对象,那么当前用户需要具有对这个基表的SELECT权限。
创建视图的命令是CREATE VIEW,这条命令的格式为:
CREATE VIEW视图名
AS SELECT语句
WITH READ ONLY
WITH CHECK OPTION;
其中最后两个选项是可选的,其中“WITH READ ONLY”限定对视图只能进行查询操作,不能进行DML操作。“WITH CHECK OPTION”限定DML操作必须满足一定的条件。
例如,下面的语句创建视图view_1,它所代表的操作是查询员工表中部门30的员工姓名、工资和奖金。
SQL>CREATE VIEW view_1 AS
SELECT ename, sal, comm FROM emp
WHERE deptno=30;
视图view_2所代表的操作是查询部门20和30中工资大于2000元的员工姓名、工资和奖金。创建这个视图的CREATE语句为:
SQL>CREATE VIEW view_2 AS
SELECT ename, sal, comm FROM emp
WHERE(deptno=30 or deptno=20)and sal>2000
视图被创建之后,可以通过DESC命令查看视图的结构。查看视图结构的方法与查看表的方法相同,查看的结果是列出视图中各列的定义。
视图的结构是在执行CREATE VIEW语句创建视图时确定的,在默认情况下,列的名称与SELECT之后基表的列名相同,数据类型和是否为空也继承了基表中的相应列。如果希望视图中的各列使用不同的名字,那么在创建视图时,在视图的名称之后应该指定各列的名称。例如,下面的语句重新创建视图view_1,并为这个视图指定了不同的名称。
CREATE VIEW view_1(name, salary, comm1)AS
SELECT ename, sal, comm FROM emp
WHERE deptno=30;
如果执行DESC命令查看视图view_1的结构,我们将发现视图中各列的名称就是在CREATE VIEW语句中指定的名称,而数据类型和是否为空继承了基表中的对应列。下面是执行DESC命令查看视图view_1结构的结果:
SQL>DESC view_1;
名称 是否为空?类型
NAME NULL VARCHAR2(10)
SALARY NULL NUMBER(7,2)
COMM1 NULL NUMBER(7,2)
视图作为一种数据库对象,它的相关信息被存储在数据字典中。与当前用户的视图有关的数据字典是USER_VIEWS,查询这个数据字典,可以获得当前用户的视图的相关信息。例如,需要查询视图VIEW_2中的相关信息,可以执行下面的SELECT语句:
SELECT text FROM user_views WHERE view_name='VIEW_2';
在列TEXT中存储的是创建视图时使用的SELECT语句。另外,在数据字典ALL_VIEWS存储的是当前用户可以访问的所有视图的信息,在数据字典DBA_VIEWS存储的是系统中的所有视图的信息,这个数据字典只有DBA可以访问。
如果发现视图的定义不合适,可以对其进行修改。实际上视图中的SELECT语句是不能直接修改的,所以修改视图的一种方法是先删除视图,再重新创建,另一种方法是在创建视图的CREATE语句中使用OR REPLACE选项。带OR REPLACE选项的CREATE语句格式为:
CREATE OR REPLACE VIEW视图名
AS SELECT语句
WITH READ ONLY
WITH CHECK OPTION;
这样在创建视图时,如果视图不存在,则创建它。如果已经存在一个同名的视图,那么先删除这个视图,然后再根据SELECT语句创建新视图,用这个新视图代替原来的视图。
视图在不需要时,可以将其从数据库中删除。删除视图的命令是DROP VIEW。用户可以直接删除自己创建的视图,如果希望删除其他用户创建的视图,则需要具有DROP ANY VIEW这个系统权限。DROP VIEW命令的格式为:
DROP VIEW视图名;
例如,要删除视图view_1,可以执行下面的语句:
DROP VIEW view_1;
视图被删除后,相关的信息也被从数据字典中删除。