【高效学数据库】视图与索引

本专栏将从基础开始,循序渐进的讲解数据库的基本概念以及使用,希望大家都能够从中有所收获,也请大家多多支持。
专栏地址: 数据库必知必会
如果文章知识点有错误的地方,请指正!大家一起学习,一起进步。
如果感觉博主的文章还不错的话,还请关注、点赞、收藏三连支持一下博主哦

视图

视图定义

在某些情况下,让所有用户看到整个逻辑模型是不合适的。例如一个职工仅可以知道教师的标识、姓名和所在系名,但是没有权限看到教师的工资值,用SQL语句的描述如下:

select ID, name, dept_name from instructor。

视图就提供了这种机制:向用户隐藏特定的数据,SQL允许通过查询来定义“虚关系”,它在概念上包含查询的结果, 但这些数据并不在硬盘上实实在在存在,像这种作为虚关系对用户可见的关系称为视图(view)。

在SQL中,我们用create view命令定义视图,命令的格式为:

create view v as < query expression >

其中

  • < query expression >可以是任何合法的查询表达式
  • v 表示视图名
  • 使用视图的目的:安全及易于使用
  • 删除视图的命令: drop view v

例1:重新考虑需要访问instructor关系中除salary之外的所有数据,此视图的定义如下:

create view faculty as 
 select ID, name, dept_name
 from instructor

例2:创建一个视图,列出Physics系在2009年秋季学期开设的所有课程,以及每个课程在哪栋建筑的哪个房间授课的信息

create view physics_fall_2009 as
 select course.course_id, sec_id, building, room_number
 from course, section
 where course.course_id = section.course_id
 and course.dept_name = ’Physics’
 and section.semester = ’Fall’
 and section.year =2009;

视图的属性名也可以按下述方式显式指定,例如列出每个系中所有教师的工资总和

create view departments_total_salary(dept_name, total_salary) as
 select dept_name, sum (salary)
 from instructor
 group by dept_name;

一旦定义了一个视图,就可以用视图名指代该视图生成的虚关系,由于数据库只存储视图定义本身,那么当视图关系出现在查询中时,它就会被已存储的查询表达式代替。

例1:使用视图physics_fall_2009,找到所有于2009年秋季学期在Watson大楼开设的Physics课程

select course_id, room_number
 from physics_fall_2009
 where building = ’Watson’;

例2:定义视图physics_fall_2009_Watson,列出于2009年秋季学期在 Watson大楼开设的所有Physics课程的标识和教室号

create view physics_fall_2009_watson as
 select course_id, room_number
 from physics_fall_2009
 where building = ’Watson’;

等价于

create view physics_fall_2009_watson as
(select course_id, room_number
from (select course.course_id, building, room_number
 from course, section
 where course.course_id = section.course_id
 and course.dept_name = ’Physics’
 and section.semester = ’Fall’
 and section.year =2009)
where building= ’Watson’

视图更新

假设我们向视图faculty插入一条新元组,可写为:

insert into faculty values (30765,‘Green’,‘Music’);

但这个插入必须表示为对instructor关系的插入,即必须给出salary的值。存在两种合理的解决方法:

  1. 拒绝插入,并向用户返回一个错误信息
  2. 向instructor关系插入元组(‘30765’,‘Green’,‘Music’, null)

mysql采用的是第2中方式,在视图中插入的数据也会出现在原数据库中,删除的数据也会在原数据库中删除。

通过视图修改数据库的另一类问题发生在这样的视图:

create view instructor_info as
 select ID, name, building
 from instructor, department
 where instructor.dept_name = department.dept_name;

这个视图列出了大学里每个教师的ID、name和建筑名。若执行以下视图插入:

 insert into instructor_info values (69987,‘White’,‘Taylor’);

假设没有标识为69987的教师,也没有位于Taylor大楼的系,唯一的解决办法是:

  1. 向instructor中插入元组(‘69987’,‘White’,null,null)
  2. 向department中插入元组(null,‘Taylor’,null)

但是以上方法显然不可行。

一般地,如果定义视图的查询对下列条件都能满足,我们称SQL视图是可更新的(updatable),即视图上可以执行插入、更新或删除:

  1. from子句中只有一个数据库关系
  2. select子句中只包含关系的属性名,不包含任何表达式、聚集或distinct声明
  3. 原数据库关系任何没有出现在select子句中的属性可以取空值;即这些没有出现的属性上没有not null约束,也不构成主码的一部分
  4. 查询中不含有group by或having子句

在上面条件的限制下,下面的视图上允许执行udpate、insert和delete 操作:

create view history_instructors as
 select *
 from instructor
 where dept_name = ’History’;

即便是在可更新的情况下,仍然存在问题。假设向视图 history_instructors 中插入元组(‘25566’,‘Brown’,‘Biology’, 100000),但这个元组并不满足视图所要求的选择条件,即dept_name需要为History。在默认情况下,SQL允许执行上述更新,但是,可以在视图定义的末尾加上with check option子句来定义视图,对更新操作进行检查。

create view history_instructors as
 select *
 from instructor
 where dept_name = ’History’ with check option ;

索引

我们用create index命令,为关系中的某些属性创建索引,它允许数据库系统高效地找到关系中那些在索引属性上取给定值的元组,而不用扫描关系中的所有元组

格式如下:

CREATE INDEX <i-name> ON <table-name> (<attribute-list>);

例:

CREATE INDEX ins_index on instructor(ID);
CREATE INDEX ins_ID_name_index on instructor(ID, name);

create unique index命令,为关系中的某些属性创建唯一索引:

CREATE UNIQUE INDEX uni_stu_index on student(ID);

drop index命令,删除一个索引

DROP INDEX <i-name>

猜你喜欢

转载自blog.csdn.net/Learning_xzj/article/details/124960330