数据库视图的概念、定义与使用

视图的概念

视图是从基本表中导出的虚拟的表,基本表需要存储数据,而视图不存储数据,只存放从基本表导出视图所需要的公式。

视图的数据是在数据库运行过程中动态产生和维护的,对基本表的修改会反映在视图的查询结果上,而对视图的修改也会作用到基本表上。

视图的定义

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 的字段,该语句尝试同时修改这两个表,因此失败。

发表评论

邮箱地址不会被公开。 必填项已用*标注