Oracle 视图
Oracle12C–对象视图(67)
注:本博客使用 scott 账号练习,再次之前需要赋予 scott 账号创建 视图的权限(使用SYS用户赋权)。
grant create view to scott;
视图是一个虚拟表,其内容由查询定义,是基于Oracle语句查询出来的结果集的可视化的表。同真实的表一样,视图包含一系列带有名称的列和行数据,犹如一个真实的表,视图中的字段就是来自一个或多个数据库中的真实的表中的字段,俗称虚表。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。
对其中所引用的基础表来说,视图的作用类似于筛选。定义视图的筛选可以来自当前或其它数据库的一个或多个表,或者其它视图。分布式查询也可用于定义使用多个异类源数据的视图。如果有几台不同的服务器分别存储组织中不同地区的数据,可以通过视图将这些服务器上相似结构的数据组合起来。
数据库中的视图一共有四种:关系视图、内嵌视图、对象视图和物化视图;
关系视图:
Oracle
视图是作为数据库对象存在的,因此,创建之后也可以通过工具或数据字典来查看视图的相关信息。这是大家常用的视图。
内嵌视图:
在 from
语句中的可以把表改成一个子查询,如:select a.id ,b.id from emp a,(select id from dept) b where a.id=b.id
内嵌视图不属于任何用户,也不是对象,内嵌视图是子查询的一种,可以与数据表、视图一样作为查询语句的数据源存在,但在形式上有较大的区别,内嵌视图不必使用 create view
命令进行创建,因此,在数据字典中也无法获得相应信息。内嵌视图的特点在于无须创建真正的数据库对象,而只是封装查询,因此会节约数据库资源,同时不会增加维护成本。但是内嵌视图不具有可复用性,因此当预期将在多处调用到同一查询定义时,还是应该使用关系视图。
对象视图:
对象类型在数据库编程中有许多好处,但有时,应用程序已经开发完成。为了迎合对象类型而重建数据表是不现实的。对象视图正是解决这一问题的优秀策略。对象视图创建之后,同样可以在数据字典中获得其相应信息。利用 Oracle
内置视图 user_views
可以获得对象视图相关信息。Oracle
中的对象数据实际仍然以关系数据的形式存储。但是,对象的特性,例如继承、封装等,都为开发人员提供了更加灵活的处理形式。同样,可以构造复杂的对象类型来封装复杂的多表查询。
物化视图:
常用于数据库的容灾,不是传统意义上虚拟视图,是实体化视图,和表一样可以存储数据、查询数据。主备数据库数据同步通过物化视图实现,主备数据库通过 data link
连接,在主备数据库物化视图进行数据复制。当主数据库垮掉时,备数据库接管,实现容灾。
权限: 要在当前用户中创建视图, 用户必须具有 create view
系统权限;要在其他用户中创建视图,用户必须具有 create any view
系统权限. 视图的功能取决于视图拥有者的权限 。
create [ or replace ] [ force ] view [schema.]view_name
[ (column1,column2,...) ]
as
select ...
[ with check option ] [ constraint constraint_name ]
[ with read only ];
解析:
DML
操作必须满足视图子查询的条件即,对通过视图进行的增删改操作进行检查,要求增删改操作的数据,必须是 select
查询所能查询到的数据,否则不允许操作并返回错误提示。 默认情况下,在增删改之前"并不会检查"这些行是否能被 select
查询检索到。举例:
创建简单视图 :是指基于单个表建立的,不包含任何函数、表达式和分组数据的视图。
create or replace view vw_emp
as SELECT EMPNO, ENAME, JOB, HIREDATE, DEPTNO FROM EMP;
创建只读视图: 只能查询,无法进行更改,如果基表有更新,只读视图也发生了相应的更改。
create view vw_emp_readonly
as select empno,ename,job,hiredate,deptno from emp
with read only;
如果尝试对视图的数据进行修改,则会报错:ORA-42399: cannot perform a DML operation on a read-only view
与简单视图类似,所以不做演示。
创建检查约束视图 with check option: 对通过视图进行的增删改操作进行检查,要求增删改操作的数据必须是select查询所能查询到的数据
create view vw_emp_check
as select empno,ename,job,hiredate,deptno from emp
where deptno = 10
with check option;
这里插入的数据如果部门编号不是10 ,则会报错:ORA-01402: view WITH CHECK OPTION where-clause violation
与简单视图类似,所以不做演示。
连接视图: 是指基于多个表所创建的视图,即,定义视图的查询是一个连接查询。 主要目的是为了简化连接查询。
create view vw_dept_emp
as select a.deptno,a.dname,a.loc,b.empno,b.ename,b.sal
from dept a,emp b
where a.deptno=b.deptno
and a.deptno in (10,30);
在视图上进行的所有DML操作,最终都会在基表上完成;select 视图没有什么限制,但insert/delete/update有一些限制;常见的DML报错为:ORA-01779: cannot modify a column which maps to a non key-preserved table。
与简单视图类似,所以不做演示,不过注意:
连接视图的更新准则
3.2.6 可更新连接视图
如果创建连接视图的select查询“不包含”如下结构,并且遵守连接视图的“更新准则”,则这样的连接视图是“可更新”的:
(union,intersect,minus)
DISTINCT
关键字GROUP BY,ORDER BY,CONNECT BY
或 START WITH
子句NOT NULL
列均属于该视图内嵌视图就是类似子查询,所以这里不在描述。
如果需要将一张数据表中的数据转换为对象的形式操作,就可以利用对象视图来完成。利用对象视图,可以将指定视图查询语句的数据按照顺序填充到相应对象的属性中,这样就可以在操作视图时直接将数据以对象的形式返回。
创建对象视图前需要创建存储数据格式的对象类。这部分这里不加描述,有时间再说。
当创建好对象类之后就可以创建对应的对象视图。
CREATE OR REPLACE VIEW 视图名称 OF 类
WITH OBJECT IDENTIFIER(主键对象)
AS 子查询;
解析:
举例:
创建一个获取 emp表 的对象视图。
-- 1.先创建一个对象类
CREATE OR REPLACE TYPE EMP_TABLE_OBJECT AS OBJECT
(
ATRI_EMPNO NUMBER(4),
ATRI_ENAME VARCHAR2(10),
ATRI_JOB VARCHAR2(9),
ATRI_MGR NUMBER(4),
ATRI_HIREDATE DATE,
ATRI_SAL NUMBER(7, 2),
ATRI_COMM NUMBER(7, 2),
ATRI_DEPTNO NUMBER(2),
MEMBER FUNCTION TOSTRING RETURN VARCHAR2
)
NOT FINAL;
/
CREATE OR REPLACE TYPE BODY EMP_TABLE_OBJECT AS
MEMBER FUNCTION TOSTRING RETURN VARCHAR2 AS
BEGIN
RETURN '雇员编号:' || SELF.ATRI_EMPNO || ',姓名:' || SELF.ATRI_ENAME || ',职位:' || SELF.ATRI_JOB || ',雇佣日期:' || SELF.ATRI_HIREDATE || ',工资:' || SELF.ATRI_SAL || ',佣金:' || SELF.ATRI_COMM;
END;
END;
/
第一步中emp_table_object
类中定义的属性与 emp
表中一样,这样就可以将 emp
表中的数据通过对象视图转变为 emp_table_object
类的对象。
-- 2.创建相关的对象视图
CREATE OR REPLACE VIEW v_myview OF emp_table_object
WITH OBJECT IDENTIFIER(ATRI_EMPNO) AS
SELECT EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO FROM EMP;
第二步将emp表中的全部数据通过对象视图转变为 emp_table_object
类的对象,这样在进行程序编写时,只需要通过对象视图就可以取得相应对象。
![04测试对象视图](D:\学习资料\个人总结文件\保存图片\视图\04测试对象视图.png)-- 3.测试创建好的对象类
DECLARE
V_EMP EMP_TABLE_OBJECT;
BEGIN
SELECT VALUE(EV) INTO V_EMP FROM V_MYVIEW EV WHERE ATRI_EMPNO = 7839;
DBMS_OUTPUT.PUT_LINE(V_EMP.TOSTRING());
END;
/
这里的程序块直接查询了对象视图,这样就会将7839雇员的信息以对象的方式返回,直接输出时,就可以调用tostring()函数取得相应的数据。
物化视图查了资料,感觉内容还是挺多的,之后再整理下。
create materialized view [view_name]
build [immediate|deferred]
refresh [fast|complete|force]
[
on [commit|demand] |
start with (start_time) next (next_time)
]
[enable | disable] query rewrite
as
{创建物化视图用的查询语句}
解析:
build [immediate|deferred]: 创建方式(BuildMethods):包括BUILD IMMEDIATE和BUILD DEFERRED两种。
BUILD IMMEDIATE: 是在创建物化视图的时候就生成数据。
BUILD DEFERRED: 则在创建时不生成数据,以后根据需要在生成数据。默认为BUILD IMMEDIATE
refresh [fast|complete|force]: 视图刷新的方式:
create materialized view log on
(主表名)。fast
模式时,数据刷新将采用 fast
方式;否则使用complete
方式。MV数据刷新的时间:
查询重写(QueryRewrite): 包括ENABLE QUERY REWRITE和DISABLE QUERY REWRITE两种。
分别指出创建的物化视图是否支持查询重写。查询重写是指当对物化视图的基表进行查询时,Oracle会自动判断能否通过查询物化视图来得到结果,如果可以,则避免了聚集或连接操作,而直接从已经计算好的物化视图中读取数据。默认为DISABLE QUERY REWRITE
。
举例:
Oracle 的物化视图的快速刷新要求必须建立物化视图日志,通过物化视图日志可以实现增量刷新功能。但是我们这边只是创建视图来查询,没有刷新,所以没有去创建物理日志表。
CREATE MATERIALIZED VIEW VM_EMP
DISABLE QUERY REWRITE
AS SELECT * FROM EMP;
-- insert
INSERT INTO VW_EMP VALUES(7322,'JORE','KING',TO_DATE('2020-01-16','YYYY-MM-DD'),10);
INSERT INTO VW_EMP VALUES(7828,'PETE','KING',TO_DATE('2020-01-16','YYYY-MM-DD'),20);
-- update
UPDATE VW_EMP SET DEPTNO = 20 WHERE ENAME = 'JORE';
-- delete
DELETE VW_EMP WHERE ENAME = 'PETE';
在对视图进行更改(或重定义)之前,需要考虑如下几个问题:
执行create or replace view语句。这种方法代替了先删除(“权限也将随之删除”)后创建的方法,会保留视图上的权限,但与该视图相关的存储过程和视图会失效。
-- 举例:将VW_EMP修改为只读
create or replace view vw_emp
as SELECT EMPNO, ENAME, JOB, HIREDATE, DEPTNO FROM EMP
with read only;
语法: alter view 视图名 compile;
**作用:**当视图依赖的基表改变后,视图会“失效”。为了确保这种改变“不影响”视图和依赖于该视图的其他对象,应该使用 alter view 语句“明确的重新编译”该视图,从而在运行视图前发现重新编译的错误。视图被重新编译后,若发现错误,则依赖该视图的对象也会失效;若没有错误,视图会变为“有效”。
**权限:**为了重新编译其他模式中的视图,必须拥有 alter any table
系统权限。
**注意:**当访问基表改变后的视图时,oracle会“自动重新编译”这些视图。
alter view vw_emp compile;
可以删除当前模式中的任何视图;
如果要删除其他模式中的视图,必须拥有DROP ANY VIEW系统权限;
视图被删除后,该视图的定义会从词典中被删除,并且在该视图上授予的“权限”也将被删除。
视图被删除后,其他引用该视图的视图及存储过程等都会失效。
drop view vw_emp; -- 删除普通视图
drop materialized view vm_emp; -- 删除物化视图