目录
定义视图
CREATE VIEW <起个视图名字>[视图的列名字们]
AS <子查询>
[WITH CHECK OPTION];
这里的子查询是一个select的语句,查询出来的结果,一列列对应视图的一列列,有的系统不能在此处的查询语句中使用groupby和distinct
注意事项
先举个例子方便下面注意事项的说明
例一
CREATE VIEW is_student (Sno,Sname,Sbirth)
AS
SELECT studentnumber,studentname,2021-studentage
FROM Student
WHERE 系名=”计算机“
WITH CHECK OPTION;
- 对视图的增删改会反映到基本表中
- 当含有WITH CHECK OPTION时对VIEW做出的增删改都需要满足子查询的WHERE条件,也就是说这里插入一个视图元组,反映到基本表上,系统会自动给这个元组的系名赋值为”计算机“
- 组成视图的列名字(Sno,Sname,Sage)要么就给全,要么就全部省略,只有这两种选择。有三种情况必须给全:子查询的某一列是聚集函数或者列表达式;多表连接时选出了几个同名列;需要为视图中某个列启用新的更适合的名字。可以发现前两个是因为VIEW根本不知道这一列该叫什么,最后一个则是根据需求来的。
- 一般在子查询中不要select *,因为到时候基本表一改,可能select出来的列数和view中就不同了,就会出错
建立视图
视图可以建立在单表、多表、表+视图的组合上
视图有多个种类
行列子集视图:
建立在单表上且没有什么创新的列,只是单纯的抽取出一些行列
包含该单表的主码
带表达式的视图:
含有虚拟列的视图,虚拟列就是原表中并不存在的列,是通过列表达式派生的。就比如例一就是带表达式的视图,因为Sbirth是通过计算的来的,基本表中根本没有这一列。
分组视图:
带有聚集函数和GROUP BY字句查询来定义视图
删除视图
DROP VIEW 表明 [CASCADE]
加CASCADE可以在删除该视图之余,把由它导出的视图也一起删了,如果某个视图还导出了子视图,不用CASCADE是删不掉这个视图的
要注意,如果删除了基本表,并不会连带删除由该表导出的视图,需要手动删除。
查询视图
查询视图和查询表的语法是一样的
两种方法:
视图消解法:通过结合视图定义中的子查询和用户的查询,将对视图的查询转换为等价的对基本表的查询,因为本来视图也是由对基本表的查询语句组成的。但消解法并不普适,有的时候不能进行转换。
例二
视图定义:CREATE VIEW S_G(Sno,Gavg) AS SELECT Sno,AVG(Grade) FROM SC GROUP BY Sno;
对视图的查询:SELECT * FROM S_G WHERE Gavg>=90;
消解法消解后:SELECT Sno,AVG(Grade) FROM SC WHERE AVG(Grade)>=60 GROUP BY Sno;
消解法只是很粗暴的把列名都对应到最初的基本表上,这样就使得聚集函数出现在了where子句中,这肯定是不对的,目前只有行列子集视图是一定可以正确转换的。
物化视图法:就是先把视图查出来作为一个表,然后对这个表进行查询,这个是Oracle的做法,所以没有消解法的问题。
更新视图
视图的更新包括插入insert 删除delete 修改update 和表一样
并不是所有的视图都是可以更新的,因为有些视图的更新不能唯一的有意义的转换成对相应基本表的更新,比如上面例二,如果更新S_G,那么它的Gavg是原来成绩的平均值,这时候你要怎么赋值原表每门课的成绩呢?
视图更新规则:
- 行列子集视图可以更新
- 两个基本表或以上导出的不能更新
- 字段来自字段表达式或常数,除了delete操作,其他不行
- 字段来自聚集函数的不许更新
- 视图定义子查询中含有GROUP BY 和DISTINCT的不许更新
- 视图中有嵌套查询,并且内层查询和外层查询是相关子查询(就是两个查询含有同一张表)的不能更新
视图的作用
- 视图能够简化用户的操作
- 视图能使用户以多种角度看待同一数据
- 对重构数据库提供了一定程度的逻辑独立性
- 对机密数据提供安全保护
- 适当利用可以更清晰的表达查询
两个思考题
什么时候定义为视图?什么时候定义为表?p123
定义视图并查询与基于派生表查询的区别?p125