视图的概念
视图是从基本表中导出的虚拟的表,基本表需要存储数据,而视图不存储数据,只存放从基本表导出视图所需要的公式。
视图的数据是在数据库运行过程中动态产生和维护的,对基本表的修改会反映在视图的查询结果上,而对视图的修改也会作用到基本表上。
视图的定义
create view view_name [列名1, 列名2, ...] as 子查询 [with check option];
定义视图时,列名可以省略,默认会使用子查询结果中的列名。
with check option
表示对视图进行更改操作(insert, update, delete)时,需要检查该记录是否满足视图定义中的查询条件。
单个表导出的视图
以下面的 Student 表为例:
这是一个基本表,我们在这个表的基础上创建一个视图 Stu_Male,该视图用于列出所有的男同学信息,定义语句如下:
create view Stu_Male as select * from Student where Sex = '男' with check option;
我们看下该视图的所有结果:
多个表导出的视图
下面是两个基本表:
左侧表同上,右侧的 Attendance 表记录了每个同学晚自习的签到次数,我们可以由多个基本表导出一个视图 Stu_Att,因此我们来创建一个包含学生学号、姓名和签到次数的视图:
create view Stu_Att(ID, Name, Count) as select ID, Name, Count from Student natural join Attendance;
这里使用内连接中的自然连接将 Student 表和 Attendance 表连接起来查询。
该视图的所有结果如下:
视图的使用
视图的查询方式和基本表的查询方式没有什么区别,但是视图的更新却存在许多限制,因此这里重点分析视图的更新操作。
若视图出现以下任意一种情况,则不能执行更新操作,只能用于查询:
- 视图的 select 目标列包含聚集函数
- 视图的 select 子句使用了 unique 或 distinct
- 视图中包括了 group by 子句
- 视图中包括经算术表达式计算出来的列
- 视图是由单个表的列构成的,但没有包括主键
对于可更新的视图而言,我们可以像更新基本表那样进行更新,不过需要注意的是,如果定义视图时标明了 with check option
,那么必须确保更改后的记录满足视图的查询条件,也就是说能被该视图查询到,否则将会失败。
更新单表导出的视图
举个例子,上面的 Stu_Male 视图在定义时,select 子句包含了 Sex = '男'
的查询条件,因此如果尝试将该视图的某条记录的 Sex 字段改为 '女',就会提示错误:
我们可以往该视图中插入性别为男的学生记录:
insert into Stu_Male values (5, '小孙', '男', 97);
更新多表导出的视图
由于 Student 表和 Attendance 表共同导出的 Stu_Att 视图,涉及到了多个基本表,因此不能执行插入和删除操作,因为这两个操作会同时影响多个基本表。
对于多表导出的视图,仍然能进行更新操作,不过要确保每次只更新一个表中的字段,否则会失败。
例如,将学生 ‘小赵’ 的签到次数更新为 8:
update Stu_Att set Count = 8 where id = 4;
视图 Stu_Att 的当前结果:
基本表 Attendance 的当前结果:
也就是说,更新 Stu_Att 视图中 Count 字段的实质是更新 Attendance 表的 Count 字段。
而如果我们尝试同时修改 Name 和 Count 这两个字段,就会出现错误:
原因就是 Name 是基本表 Student 的字段,而 Count 是基本表 Attendance 的字段,该语句尝试同时修改这两个表,因此失败。
作者:Wray Zheng
原文:http://www.codebelief.com/article/2018/03/database-view-concept-define-and-usage/