目录
视图的作用
创建视图
为 scott 分配创建视图的权限
查询视图
复杂视图的创建
视图更新的限制问题
更新视图中数据的部门编号(视图的存在条件)
限制通过视图修改数据表内容
创建只读的视图
复杂视图创建
oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645
视图的作用
在所有的 SQL 语句中,查询是最复杂的操作之一,而且查询还和具体的开发要求有关,那么在开发过程中,程序员完成的并不是与数据库相关的所有内容,而应该更多地考虑到程序的设计结构。
可是没有一个项目里面会不包含复杂查询,那么程序员如何从复杂查询中解脱出来呢?
这种情况下就提出了视图的概念。利用视图可以实现复杂 SQL 语句的封装操作。
从实际开发来说,一个优秀的数据库设计人员,除了要给出合理的数据表结构,还应该将所有可能使用到的查询封装好视图,一并交给开发者。
视图可以看成是一张虚拟表,由存储的查询组成。
视图和真实的数据表一样,都包含若干行和列。
但是,在视图中并不存储数据,其数据仍然来源于视图定义时所使用的数据表中,数据库只在数据字典中存储视图的定义信息
create [OR REPLACE] VIEW 视图名称 AS 子查询 ;
创建视图
CREATE VIEW myview AS SELECT * FROM emp WHERE deptno=10 ;
这个语句实现将部门 10 的所有员工信息保存在视图中。
在 Oracle 10g 及以前的版本中,scott 是可以直接进行视图创建的,但是从 Oracle 10g R2 版本开始,如果想创建视图,就需要单独分配创建视图的权限
为 scott 分配创建视图的权限
CONN sys/change_on_install AS SYSDBA ;
GRANT CREATE VIEW TO scott ;
CONN scott/tiger ;
权限分配完成之后就可以进行视图的创建操作了。视图本身属于数据库对象,所以查看视图的信息可以使用“user_views”数据字典完成。
在这个数据字典里面可以查询到视图的具体语法。视图可以像普通的数据表那样直接进行查询
查询视图
SELECT * FROM myview ;
发现查询视图与之前直接使用 SELECT 查询语句所得到的结果是完全相同的,所以视图就封装了SQL 语句,而开发者可以通过视图简单地查询到所需要的数据。
下面继续利用视图封装一个复杂的 SQL
复杂视图的创建
DROP VIEW myview ;
CREATE VIEW myview AS
SELECT d.deptno,d.dname,d.loc,temp.count
FROM dept d,(SELECT deptno dno,COUNT(*) countFROM empGROUP BY deptno) temp
WHERE d.deptno=temp.dno(+) ;
由于 myview 视图的名称已经被占用,所以理论上应该先删除,而后再创建一个新的视图,可是删除和创建之间有可能产生间隔。
其中 DROP VIEW 是删除视图的语句。所以在实际开发中,由于视图使用频率较高,而且直接与开发有关系,一般情况下不会选择删除后再重新创建,而是选择进行视图的替换。利用新的查询替换掉旧的查询
CREATE OR REPLACE VIEW myview AS
SELECT d.deptno,d.dname,d.loc,temp.count
FROM dept d,(SELECT deptno dno,COUNT(*) countFROM empGROUP BY deptno) temp
WHERE d.deptno=temp.dno(+) ;
上面这个语句表示,如果视图存在则进行替换,如果视图不存在则进行删除
从开发分工来说,此部分的操作应该是由数据库开发人员进行的,但是从现实来说,基本上除了大的开发团队,大部分的中小开发团队都会由开发人员自己编写
视图更新的限制问题
视图中只是包含查询语句的临时数据,并不是真实存在的,可是在默认情况下,创建的视图是可以直接进行修改操作的
更新视图中数据的部门编号(视图的存在条件)
CREATE OR REPLACE VIEW myview AS
SELECT * FROM emp WHERE deptno=20 ;
此时在创建的 myview 视图中,deptno=20 是视图数据的存在依据,但是在默认情况下,可以通过视图修改原数据表中的信息。
下面修改其中一行数据的部门编号
UPDATE myview SET deptno=30 WHERE empno=7369 ;
发现此时更新了视图,结果导致 emp 数据表中的内容也发生了变化。
为了保证视图的创建条件不能够被更新,可以在创建视图的时候使用 WITH CHECK OPTION 子句
限制通过视图修改数据表内容
CREATE OR REPLACE VIEW myview AS
SELECT * FROM emp WHERE deptno=20
WITH CHECK OPTION ;
此时使用了 WITH CHECK OPTION 子句可以保证视图的创建条件不被更新
UPDATE myview SET deptno=30 WHERE empno=7566 ;
将出现如下的错误“提示信息:ORA-01402: 视图 WITH CHECK OPTION WHERE 子句违规”,即视图创建条件的字段不能修改。
但是视图中不仅仅只存在有创建条件的字段,还可能会包含其他字段。在现实操作中,可以修改视图中的其他字段内容
UPDATE myview SET sal=80000 WHERE empno=7369 ;
此时更新操作成功了
发现视图更新时改变的是数据表中的数据,这样的做法同样也不合理。
所以一般在创建视图的时候,由于里面都属于映射的数据,那么本质上就不建议对其进行修改,最好就是创建一个只读视图。
使用 WITH READ ONLY 子句完成
创建只读的视图
CREATE OR REPLACE VIEW myview AS
SELECT * FROM emp WHERE deptno=20
WITH READ ONLY ;
现在就创建好了一个只读视图信息,于是再次发出修改操作时,会出现“ORA-42399: 无法对只读视图运行 DML 操作”,这样就避免了通过视图的临时数据修改数据表的真实数据。
前面介绍了视图的创建,然而实际上如果是单张表的查询,建立视图并没有太大的作用,视图主要用来封装复杂查询,例如来源于多个表
下面是一个复杂查询的封装
复杂视图创建
CREATE OR REPLACE VIEW myview AS
SELECT e.empno,e.ename ename,e.job,d.dname,e.sal,m.ename mname
FROM emp e,dept d,emp m
WHERE e.deptno=d.deptno AND e.mgr=m.empno(+) ;
直接进行下面的更新操作
UPDATE myview SET sal=8000,dname='SALES',mname='KING'
WHERE empno=7902 ;
此时没有增加“WITH CHECK OPTION、WITH READ ONLY”等限制条件,但是运行时出现错误信息“ORA-01776: 无法通过联接视图修改多个基表”。如果真的需要修改数据表的内容,可以使用替代触发器完成