Oracle视图

Oracle视图

文章目录

    • Oracle视图
      • 视图定义
      • 视图的优缺点
        • 优点:
        • 缺点:
      • 视图的分类
      • 视图的创建
        • **关系视图**
        • 内嵌视图
        • 对象视图*
        • 物化视图*
      • 简单视图的DML操作
      • 更改视图
        • 更改视图定义
        • 视图重新编译
      • 删除视图

参考博客:

Oracle 视图

Oracle12C–对象视图(67)

注:本博客使用 scott 账号练习,再次之前需要赋予 scott 账号创建 视图的权限(使用SYS用户赋权)。

grant create view to scott;

视图定义

视图是一个虚拟表,其内容由查询定义,是基于Oracle语句查询出来的结果集的可视化的表。同真实的表一样,视图包含一系列带有名称的列和行数据,犹如一个真实的表,视图中的字段就是来自一个或多个数据库中的真实的表中的字段,俗称虚表。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。

对其中所引用的基础表来说,视图的作用类似于筛选。定义视图的筛选可以来自当前或其它数据库的一个或多个表,或者其它视图。分布式查询也可用于定义使用多个异类源数据的视图。如果有几台不同的服务器分别存储组织中不同地区的数据,可以通过视图将这些服务器上相似结构的数据组合起来。

视图的优缺点

优点:

  1. 数据安全:对不同的用户定义不同的视图,使用户只能看到与自己有关的数据,同时,用户对视图,不可以随意的更改和删除。
  2. 聚焦数据: 视图提供了一种可以控制的方式, 即可以让不同的用户看见不同的列, 而不允许访问那些敏感的列, 这样就可以保证敏感数据不被用户看见;
  3. 简化查询:为复杂的查询建立一个视图,可以快速访问两表或多表连接所组成的数据。 可以把一些多表的数据组合在一块,可以快速读取用聚合函数返回的结果集。
  4. 逻辑数据独立性: 将程序与表通过视图分隔开来,在做复杂的查询逻辑时可以简化思考过程;
  5. 简化用户权限的管理:可以将视图的权限授予用户, 而不必将基表中某些列的权限授予用户, 这样就简化了用户权限的定义。
  6. 重定义列名:在表中有些列名定义没有代表意义,可以在组建视图时重命名列名。
  7. 可以合并分离的数据,创建分区视图 。当数据量大的时候,这时我们就可以使用union关键字, 将各分公司的数据合并为一个视图。
  8. 视图还可以用作跨表及跨域,在两台数据库之间做桥梁链接的作用.

缺点:

  1. 性能:必须把视图的查询转化成对基本表的查询,如果这个视图是由一个复杂的多表查询所定义,那么,即使是视图的一个简单查询,也会把它变成一个复杂的结合体,需要花费一定的时间。
  2. 当用户试图修改试图的某些信息时,数据库必须把它转化为对基本表的某些信息的修改,对于简单的试图来说,这是很方便的,但是,对于比较复杂的试图,可能是不可修改的。
  3. 维护繁琐:在后期的维护上 数据库的表结构变了 也会影响视图的改变,维护繁琐。

视图的分类

数据库中的视图一共有四种:关系视图、内嵌视图、对象视图和物化视图

关系视图:

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 ];

解析:

  1. or replace: 如果存在同名的视图,则使用新视图"替代"已有的视图;
  2. force: 强制创建视图,不考虑基表是否存在,也不考虑是否具有使用基表的权限(当基表出现问题时不能创建视图,通过这个关键字可以强制创建);
  3. column1,column2,。。。: 视图的列名,列名的个数必须与select查询中列的个数相同; 如果select查询包含函数或表达式,则必须为其定义列名。此时,既可以用column1,column2指定列名,也可以在select查询中指定列名。
  4. with check option: 指定对视图执行的 DML 操作必须满足视图子查询的条件即,对通过视图进行的增删改操作进行检查,要求增删改操作的数据,必须是 select 查询所能查询到的数据,否则不允许操作并返回错误提示。 默认情况下,在增删改之前"并不会检查"这些行是否能被 select 查询检索到。
  5. **with read only:**创建的视图只能用于查询数据,而不能用于更改数据。

举例:

创建简单视图 :是指基于单个表建立的,不包含任何函数、表达式和分组数据的视图。

create or replace view vw_emp 
as SELECT EMPNO, ENAME, JOB, HIREDATE, DEPTNO FROM EMP;

Oracle视图_第1张图片

创建只读视图: 只能查询,无法进行更改,如果基表有更新,只读视图也发生了相应的更改。

 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。

与简单视图类似,所以不做演示,不过注意:

  1. 如果连接视图中的一个**基表的键(主键、唯一键)**在它的视图中仍然存在,并且“基表的键”仍然是“连接视图中的键”(主键、唯一键);即,某列在基表中是主键|唯一键,在视图中仍然是主键|唯一键,则称这个基表为“键值保存表”。
    一般地,由主外键关系的2个表组成的连接视图,外键表就是键值保存表,而主键表不是。

连接视图的更新准则

  1. 一般准则
    • 任何DML操作,只能对视图中的键值保存表进行更新, 即,“不能通过连接视图修 改多个基表”。
    • 在DML操作中,“只能使用连接视图定义过的列”。
    • 自连接视图”的所有列都是可更新(增删改)的。
  2. insert准则
    • 在insert语句中不能使用“非键值保存表”中的列(包括“连接列”);
    • 执行insert操作的视图,至少应该“包含”键值保存表中所有设置了约束的列;
    • 如果在定义连接视图时使用了WITH CHECK OPTION 选项,则“不能”针对连接视 图执行insert操作
  3. update准则
    • 键值保存表中的列是可以更新的;
    • 如果在定义连接视图时使用了WITH CHECK OPTION 选项,则连接视图中的连接列(一般就是“共有列”)和基表中的“其他共有列”是“不可”更新的,连接列和共有列之外的 其他列是“可以”更新的
  4. delete准则
    • 如果在定义连接视图时使用了WITH CHECK OPTION 选项,依然“可以”针对连接视图执行delete操作

3.2.6 可更新连接视图

如果创建连接视图的select查询“不包含”如下结构,并且遵守连接视图的“更新准则”,则这样的连接视图是“可更新”的:

  1. 集合运算符 (union,intersect,minus)
  2. DISTINCT 关键字
  3. GROUP BY,ORDER BY,CONNECT BYSTART WITH 子句
  4. 子查询
  5. 分组函数
  6. 需要更新的列不是由“列表达式”定义的
  7. 基表中所有 NOT NULL 列均属于该视图

内嵌视图

内嵌视图就是类似子查询,所以这里不在描述。

对象视图*

如果需要将一张数据表中的数据转换为对象的形式操作,就可以利用对象视图来完成。利用对象视图,可以将指定视图查询语句的数据按照顺序填充到相应对象的属性中,这样就可以在操作视图时直接将数据以对象的形式返回。

创建对象视图前需要创建存储数据格式的对象类。这部分这里不加描述,有时间再说。

当创建好对象类之后就可以创建对应的对象视图。

CREATE OR REPLACE VIEW 视图名称 OFWITH OBJECT IDENTIFIER(主键对象)
AS 子查询;

解析:

  1. OF语句: 表示数据要转换为对象的所属类,
  2. WITH OBJECT IDENTIFIER: 表示要设置一个对象标识符(OID),对象标识符的主要功能是使用一个个标记来唯一地标记一个对象,当创建完是对象视图后,Oracle会自动产生一个OID。

举例:

创建一个获取 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 类的对象。

Oracle视图_第2张图片

-- 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 类的对象,这样在进行程序编写时,只需要通过对象视图就可以取得相应对象。

Oracle视图_第3张图片

![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()函数取得相应的数据。

Oracle视图_第4张图片

物化视图*

物化视图查了资料,感觉内容还是挺多的,之后再整理下。

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 
	{创建物化视图用的查询语句} 

解析:

  1. build [immediate|deferred]: 创建方式(BuildMethods):包括BUILD IMMEDIATE和BUILD DEFERRED两种。

    • BUILD IMMEDIATE: 是在创建物化视图的时候就生成数据。

    • BUILD DEFERRED: 则在创建时不生成数据,以后根据需要在生成数据。默认为BUILD IMMEDIATE

  2. refresh [fast|complete|force]: 视图刷新的方式:

    • fast: 增量刷新.假设前一次刷新的时间为t1,那么使用fast模式刷新物化视图时,只向视图中添加t1到当前时间段内,主表变化过的数据.为了记录这种变化,建立增量刷新物化视图还需要一个物化视图日志表。create materialized view log on(主表名)。
    • complete: 全部刷新。相当于重新执行一次创建视图的查询语句。
    • force: 这是默认的数据刷新方式。当可以使用 fast 模式时,数据刷新将采用 fast 方式;否则使用complete 方式。
  3. MV数据刷新的时间:

    • on demand: 在用户需要刷新的时候刷新,这里就要求用户自己动手去刷新数据了(也可以使用job定时刷新)
    • on commit: 当主表中有数据提交的时候,立即刷新MV中的数据;
      **start ……:**从指定的时间开始,每隔一段时间(由next指定)就刷新一次。
  4. 查询重写(QueryRewrite): 包括ENABLE QUERY REWRITEDISABLE QUERY REWRITE两种。

    分别指出创建的物化视图是否支持查询重写。查询重写是指当对物化视图的基表进行查询时,Oracle会自动判断能否通过查询物化视图来得到结果,如果可以,则避免了聚集或连接操作,而直接从已经计算好的物化视图中读取数据。默认为DISABLE QUERY REWRITE

举例:

Oracle 的物化视图的快速刷新要求必须建立物化视图日志,通过物化视图日志可以实现增量刷新功能。但是我们这边只是创建视图来查询,没有刷新,所以没有去创建物理日志表。

CREATE MATERIALIZED VIEW VM_EMP
DISABLE QUERY REWRITE
AS SELECT * FROM EMP;

Oracle视图_第5张图片

简单视图的DML操作

-- 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';

Oracle视图_第6张图片

更改视图

在对视图进行更改(或重定义)之前,需要考虑如下几个问题:

  1. 由于视图只是一个虚表,其中没有数据,所以更改视图只是改变数据字典中对该视图的定义信息,视图的所有基础对象都不会受到任何影响。
  2. 更改视图之后,依赖于该视图的所有视图和PL/SQL程序都将变为INVALID(失效)状态
  3. 如果以前的视图中具有with check option选项,但是重定义时没有使用该选项,则以前的此选项将自动删除。

更改视图定义

执行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;  -- 删除物化视图

你可能感兴趣的:(Oracle,基础)