Oracle数据库视图概述
视图介绍
视图是一个或多个表的逻辑表示形式。
视图在本质上是一个存储的查询(定义视图的查询中不能包含 FOR UPDATE 子句)。
视图的数据来自它所依赖的称为基表的表。基表可以是表或其他视图。在视图上执行的所有操作实际上都影响到基表。
在大多数可以使用表的地方,也可以使用视图。
注意:物化视图与常规视图不同,物化视图结构保存查询的结果数据,后续文章中详细介绍
视图优点
视图能够为不同类型的用户定制数据表示形式。视图的主要优点如下:
1、通过限制对一组预定义的表行或表列的访问,提供一个额外的表安全级别
2、隐藏数据复杂性
例如,一个单一视图的定义可以包含一个联接,它是多个表中的相关列或行的集合。不过,视图隐藏了一个事实,即此信息实际上来自于几个表。查询还可能会对表的信息执行大量计算。因此,用户可以查询视图,而不用知道如何执行联接或计算。
3、以一个不同于基表的角度来呈现数据。例如,可以重命名视图的列,而不会影响视图所基于的表。
4、隔离应用程序和对基表定义的更改
例如,如果视图的查询定义引用了一个四列表的其中三列,若添加第五列到该表,则视图的定义不会受到影响,并且使用该视图的所有应用程序也不会受到影响。
案例
考虑表 hr.employees,它具有多个列和许多行。要允许用户只能查看其中 5 列,或只能查看某些特定的行,可以创建一个视图,如下所示:
CREATE VIEW v_staff AS
SELECT employee_id, last_name, job_id,
manager_id, department_id
FROM employees;
上线创建的 v_staff视图只显示了基表中的五列。
视图特征
与表不同,视图既不分配存储空间,也不包含数据。而是通过定义一个查询,从它所引用的基表中提取或派生出数据。
视图基于其他对象,除了只需要在数据字典中存储定义视图的查询,它不需要其他存储。
视图对其所引用的对象存在的依赖关系,由数据库自动处理。例如,如果删除并重新创建了视图的基表,则数据库会确定新的基表是否仍然适合该视图的定义。
视图中的数据操作
由于视图是从表派生的,所以他们有很多相似之处。例如,与表一样,一个视图可以包含多达 1000 个列。
用户可以查询视图,在某些限制条件下他们也可以在视图上执行 DML。
在视图上执行的操作会影响到视图的基表中的数据,并遵从基表的完整性约束和触发器。
案例
下面的示例创建 hr.employees 表上的一个视图:
CREATE VIEW v_staff_dept_10 AS
SELECT employee_id, last_name, job_id,
manager_id, department_id
FROM employees
WHERE department_id = 10
WITH CHECK OPTION CONSTRAINT staff_dept_10_cnst;
该查询定义只引用了部门 10 中的行。
使用 CHECK OPTION 创建的视图具有一个约束,如果对该视图发出的 INSERT 和 UPDATE 语句所生成的新行不符合该视图的选择条件,则该语句将不会成功。
因此,行 10 部门的雇员可以插入,但是部门 30 的行不可以。
在视图中,数据是如何访问的
Oracle 数据库将视图定义存储在数据字典中,存的是定义视图查询的文本 。
当在 SQL 语句中引用视图时,数据库将执行以下任务:
1、(尽可能)将所发出的查询,与定义该视图(或其它任何底层视图)的查询进行合并
Oracle 数据库会优化合并的查询,就好像发出的查询并没有引用视图一样。因此,数据库可以使用任何被引用基表列上的索引,无论在视图定义中或在针对该视图的用户查询中是否引用了该列。
有时数据库不能将视图定义与用户查询合并。在这种情况下,数据库可能不会使用所有引用列上的索引。
2、在一个共享 SQL 区中,解析合并后的语句
只要存在包含相似语句的共享 SQL 区,oracle 数据库就会在一个共享 SQL 区中解析这个引用了视图的语句。
3、执行具体的 SQL 语句
案例
面的示例演示了当查询视图时的数据访问。假设创建基于 employees表和 departments 表 employees_view 视图:
create view employees_view
as
SELECT employee_id, last_name, salary, location_id
FROM employees JOIN departments USING (department_id)
WHERE departments.department_id = 10;
用户对 employees_view 执行如下的查询:
SELECT last_name
FROM employees_view
WHERE employee_id = 9876;
Oracle 数据库将视图和用户查询合并,构建如下面的查询,然后执行此查询以检索数据:
SELECT last_name
FROM employees, departments
WHERE employees.department_id = departments.department_id
AND departments.department_id = 10
AND employees.employee_id = 9876;
可更新联接视图
定义: FROM 子句中有多个表或视图的视图。
实际环境中很少使用这种可更新的联结视图,了解即可。
案例
在示例中,staff_dept_10_30 视图将 employees 表和 departments 表相连接,只包括部门 10 或 30 的雇员。
CREATE VIEW staff_dept_10_30 AS
SELECT employee_id, last_name, job_id,
e.department_id
FROM employees e, departments d
WHERE e.department_id IN (10, 30)
AND e.department_id = d.department_id;
可更新联接视图,也叫做可修改联接视图,涉及两个或多个基表或视图,并允许 DML 操作。
可更新视图在 SELECT 语句的顶层 FROM 子句中包含多个表,并且没有 WITH READ ONLY 子句限制。
要使视图天生就可更新,必须满足几个条件。例如,一般的原则是联接视图上的插入、 更新、或删除操作只可一次修改一个基表。如下的对数据字典视图 USER_UPDATABLE_COLUMNS 的查询显示在案例中创建的视图是可更新的:
SELECT TABLE_NAME, COLUMN_NAME, UPDATABLE
FROM USER_UPDATABLE_COLUMNS
WHERE TABLE_NAME = 'STAFF_DEPT_10_30';
TABLE_NAME COLUMN_NAME UPDATABLE
STAFF_DEPT_10_30 EMPLOYEE_ID YES
STAFF_DEPT_10_30 LAST_NAME YES
STAFF_DEPT_10_30 JOB_ID YES
STAFF_DEPT_10_30 DEPARTMENT_ID YES
连接视图中的所有可更新列,必须映射到键保留表中的列。
联接查询中的键保留表,其基表中的每一行在查询输出中最多出现一次。
在示例 中,department_id 是 departments 表的主键,所以 employees 表中的每一行在结果集中最多出现一次,使得 employees 表是键保留的。而departments 表不是键保留的,因为其每个行可能会在结果集中多次出现。
对象视图
正如一个视图是一个虚拟表,一个对象视图是一个虚拟对象表。
在视图中的每一行都是一个对象,对象是某种对象类型的一个实例。
对象类型是一种用户定义的数据类型。
可以检索、 更新、 插入、和删除关系数据,如同它被存储为一个对象类型。
还可以用对象数据类型的列来定义视图,如对象、 REF、和集合(嵌套表和 VARRAYs)等。
与关系型视图类似,对象视图可以只显示希望用户看到的数据。例如,一个对象视图可以只呈现 IT 程序员的有关信息,但忽略有关薪水等敏感数据。
案例
下面的示例创建一个 employee_type 对象,然后创建基于此对象的视图 it_prog_view:
CREATE TYPE employee_type AS OBJECT
(
employee_id NUMBER (6),
last_name VARCHAR2 (25),
job_id VARCHAR2 (10)
);
CREATE VIEW it_prog_view OF employee_type
WITH OBJECT IDENTIFIER (employee_id) AS
SELECT e.employee_id, e.last_name, e.job_id
FROM employees e
WHERE job_id = 'IT_PROG';
对象视图在原型程序或向面向对象转换的应用程序中非常有用,因为视图中的数据可以取自关系表,而访问起来好像是一个对象表。
可以运行面向对象的应用程序,而不用将现有表转换为不同的物理结构。