-
一、什么是视图
1、认识视图
根据官方的文档可以这么理解视图:它是一个基于一个表或多个表的逻辑表,视图本身不包含任何数据。通俗来说,可以把视图看成是虚拟的表,只是一个查询语句的结果,它的数据最终是从表中获取的,这些表通常称为源表或基表。当基表的数据发生变化时,视图里的数据同样发生变化。通常视图的数据源有下面三种情况:
- 单一表的子集
- 多表操作的结果集
- 视图的子集
2、视图的作用
■ 简化数据。表中的很多数据对业务来说是冗余的,这时开发者会使用比较复杂的SQL语句得到自己想要的结果。但实际开发中不能要求每个人都能做到这一点,所以,通常情况下由一个人把该复杂语句做成视图,其他人员直接调用该视图即可。这样对视图的使用人员就简化了数据,从而隐藏了数据的复杂性。
■ 使数据更加独立。程序开发时,大多的设计是程序直接访问数据库的表,但当这些表的结构随着业务的变化而不得不重新设计时会影响到程序(通常表一旦设计完成就很难再做修改),所以可以使得程序直接访问视图。这样,通过视图就可以把程序和数据库的表隔离开来,降低开发者的劳动成本。
■ 增加安全性。使用视图可以查询表的指定列来展现给用户,而不必让使用者完全看见表中的所有字段。这种情况多见于一个公司提供给其他合作伙伴查询数据的接口,而视图通常也会设成只读属性。
3、视图的语法
CREATE [ OR REPLACE ] [ [ NO ] FORCE ] VIEW
[ schema. ]view
[(alias,...) inline_constraint(s)]
[out_of_line_constraint(s)]
AS subquery
[
WITH { READ ONLY | CHECK OPTION [ CONSTRAINT constraint ] }
];
【语法说明】
■ OR REPLACE:表示新建视图可以覆盖同名视图。
■ [ NO ] FORCE:即FORCE或NOFORCE,表示是否强制创建视图。例如,在基表不存在的情况下就创建视图是错误的,这时可以用FORCE关键字强制创建视图,然后再创建基表。Oracle中NOFORCE是默认值。
■ [ schema. ]view:这是视图的所属模式的名称和视图本身的名称。
■ [(alias,...) inline_constraint(s)]:视图字段的别名和内联约束。
■ [out_of_line_constraint(s)]:也是约束,是与inline_ constraint(s)相反的声明方式。
■ WITH READ ONLY:设置视图只读特性,这样的视图具有更高的安全性。
■ WITH CHECK OPTION [ CONSTRAINT constraint ]:一旦使用该限制,当对视图增加或修改数据时必须满足子查询的条件。也就是说,是把子查询的条件作为一个约束,而constraint是这个约束的名称。
注意 语法中的大括号表示必选语法项,这里只是说明WITH后面必须接大括号里面的内容。
二、创建视图
1.创建单表视图
还是以PRODUCTINFO(产品信息表)和CATEGORYINFO(产品类型表)为基础如图:
注意 根据官方提供的资料,在当前用户下创建视图需要有CREATE VIEW系统权限,这里直接给当前用户赋予了DBA权限。
【示例1】创建单表视图
这个单表视图的作用是展示5行产地为“中国”的数据。在SQL*Plus中编写如下脚本并执行:
01 CREATE OR REPLACE VIEW SIMPLE_PRODUCTINFO_VIEW
02 AS
03 SELECT PRODUCTID, PRODUCTNAME, PRODUCTPRICE, CATEGORY, ORIGIN
04 FROM PRODUCTINFO
05 WHERE ORIGIN = '中国'
06 AND ROWNUM < 6;
- 【代码解析】
- 第1行表示创建或覆盖名称为SIMPLE_PRODUCTINFO_VIEW的视图。如果没有OR REPLACE 关键字,则表示只创建视图而不能覆盖同名视图。
- 第5行表示只列出产地是“中国”的数据。
- 第6行中的ROWNUM < 6表示列出5条数据。ROWNUM是一个伪列,也就是说表中没有该字段,利用它可以限制返回的行数。它总是从1开始增加,这个特点决定了使用它时通常都是用ROWNUM < n(n>1)或ROWNUM = 1的格式作为条件。
2、创建多表视图
【示例2】创建多表视图
下面创建的视图是把PRODUCTINFO和CATEGORYINFO这两个表关联起来查询的,目的是把商品类型编码替换成商品类型。
01 CREATE OR REPLACE VIEW MULTI_PRODUCTINFO_VIEW
02 AS
03 SELECT PT.PRODUCTID, PT.PRODUCTNAME, PT.PRODUCTPRICE, PT.CATEGORY,
04 CG.CATEGORYNAME, PT.ORIGIN
05 FROM PRODUCTINFO PT,CATEGORYINFO CG
06 WHERE PT.CATEGORY = CG.CATEGORYID
07 AND PT.ORIGIN = '中国'
08 AND ROWNUM < 10;
【代码解析】
- 第1行表示创建或覆盖名称为MULTI_PRODUCTINFO_VIEW的视图。
- 第3行和第4行的字段前面多了“PT”或“CG”字样,这是表的别名,这样使读者能够直观地了解到该字段属于哪个表。
- 第4行的CG.CATEGORYNAME字段表示产品类型名称。
- 第6行表示查询数据的条件之一是把PRODUCTINFO表中CATEGORY字段和CATEGORYINFO表中CATEGORYID字段值相等的记录关联起来,以达到把商品类型编码替换成商品类型的目的。
- 第7行和第8行脚本的详细解释参考“示例1”。
其实还可以创建视图的视图和没有源表的视图,但是日常使用较少,这里不过多介绍。
三、操作视图数据的限制
视图允许做DML操作,但需要注意的地方比较多。因为对视图增加或更新数据实际上是在操作视图的源表。除此之外,视图本身可以设置更新的限制条件。本节主要介绍对视图数据做更新操作的相关注意事项。
1、视图的READ ONLY属性设置
【示例3】创建只读属性的视图-----------创建视图时为了避免用户修改数据,可以把视图设成只读属性
01 CREATE OR REPLACE VIEW SIMPLE_PRODUCTINFO_VIEW AS
02 SELECT PRODUCTID, PRODUCTNAME, PRODUCTPRICE, CATEGORY, ORIGIN
03 FROM PRODUCTINFO
04 WHERE ORIGIN = '中国'
05 WITH READ ONLY
【代码解析】
■ 第5行是本小节的重点,通过这个选项可以设置该视图只读。当插入或修改视图数据时,会提示“无法对只读视图执行DML操作”的信息。
2、视图的CHECK OPTION属性设置
CHECK OPTION选项表示视图启动了和子查询条件一样的约束。也就是说,如果对视图进行修改或插入的数据与查询条件不一致,那么该操作会被中止。
【示例4】创建带检查约束的视图
01 CREATE OR REPLACE VIEW SIMPLE_PRODUCTINFO_VIEW AS
02 SELECT PRODUCTID, PRODUCTNAME, PRODUCTPRICE, CATEGORY, ORIGIN
03 FROM PRODUCTINFO
04 WHERE ORIGIN = '中国'
05 WITH CHECK OPTION
【代码解析】
■ 第5行表示开启了条件检查。这时如果要增加或修改数据,就要符合WHERE后面的条件,即ORIGIN字段的值是“中国”。
【执行效果】
以上脚本创建的视图的数据要求只列出产地是中国的商品。查询后列表如下图所示。
为了验证视图的CHECK OPTION设置是否生效,下面在PL/SQL Developer工具中对视图进行DML操作。
(1)增加数据
执行如下增加语句:
INSERT INTO SIMPLE_PRODUCTINFO_VIEW
(PRODUCTID,PRODUCTNAME,PRODUCTPRICE,CATEGORY,ORIGIN)
VALUES('0240050005','测试',400.00,'0100040001','美国')
这里增加的数据的ORIGIN字段值是“美国”,它和视图的查询条件不一致,那么会出现错误提示,如下图所示。
(2)修改数据
对视图的某条记录进行修改,执行如下语句:
UPDATE SIMPLE_PRODUCTINFO_VIEW
SET ORIGIN = '美国'
WHERE PRODUCTID = '0240020001'
以上脚本把视图里产品编号为0240020001的数据的ORIGIN字段值修改为“美国”,但依然提示图9-14所示的错误。
(3)删除数据
在表PRODUCTINFO中有一条数据的ORIGIN字段的值是“美国”,接下来我们对视图执行删除操作。脚本如下:
DELETE FROM SIMPLE_PRODUCTINFO_VIEW
WHERE ORIGIN = '美国'
脚本执行后并没有出现错误提示,但会提示0行被操作。这不但说明视图过滤出来的数据和源表的数据在逻辑上是彻底分离的,也说明了CHECK OPTION项对删除操作不起作用(如果有作用,删除语句将无法执行)。
3、 视图创建语句对视图操作的影响
如果想要一个可以更新(这里的更新是指增加、删除、修改)的视图,则其源表尽量是单表,否则限制会比较多。下面的情况一旦出现在视图中,视图就不允许更新。
■ DISTINCT关键字。
■ 集合运算或分组函数。如INTERSECT、SUM、MAX、COUNT等函数。
■ 出现GROUP BY、ORDER BY、MODEL、START WITH等语句。
■ 出现伪列关键字,如ROWNUM。
除了以上情况外,还需要考虑基表的一些约束,这些约束对视图数据的更新都有一定影响。如果需要创建可以更新的视图,可以使用INSTEAD OF触发器。
最后留给小伙伴们一个思考题:
当对视图做删除数据操作时,如果视图里没有符合条件的数据,但基表存在符合条件数据,实际会出现什么情况?
到此,视图学习告一段落,欢迎纠正,欢迎补充。
本博客主要引自:《零基础学Oracle》 — 赵雪 胡可 王建强