背景
之前使用的select,insert,update,delete等,都是在逻辑模型曾操作,也就是说我们假定给定关系是实际存储在数据库中的。
出于安全的考虑,让所有用户都看到整个逻辑模型是不合适的。除过安全的考虑,还可能希望创建一个比逻辑模型更符合特定用户直觉的个人化关系集合。比如希望有一个关于physics系在2009年秋季学期开设的所有课程段列表,包含每个课程段在哪栋建筑的哪个房间授课:
SELECT course.course_id, section.sec_id, section.building, section.room_numberFROM section, courseWHERE section.course_id = course.course_id AND dept_name = 'Physics' AND section.semester = 'Fall'AND section.year = '2009';
![6370b019377bd1bd4a5f2f41d5cbd3f9.png](https://i-blog.csdnimg.cn/blog_migrate/dc1498855466a2da8036dc4ee8493f41.jpeg)
我们可以把上述查询结果保存下来提供给用户。但是一旦course,section底层数据发生变化,那么上面的结果就与重新执行查询的结果不匹配。
相反,SQL可以通过“查询”定西“虚关系”。虚关系并不预先计算并存储,只是在使用的时候才通过执行查询进行计算,这种作为虚关闭对用户可见的关系称为视图。
SQL视图定义
使用create view定义视图,考虑需要访问instructor关系中除salary之外的数据的职员,可以把视图关系faculty提供给职员,定义如下:
CREATE VIEW faculty AS SELECT id, name, dept_name FROM instructor;
数据库系统存储与视图相关联的查询表达式。当视图关系被访问时,其中的元组(记录)是通过计算查询结果而被创建出来的。视图关系实在需要的时候才被创建的。创建视图:列出physics系在209年秋季学期所开设的所有课程段以及每个课程段在哪栋建筑的哪个房间授课的信息。
CREATE VIEW physics_fall_2009 AS SELECT course.course_id, section.sec_id, section.building, section.room_number FROM section, course WHERE section.course_id = course.course_id AND dept_name = 'Physics' AND section.semester = 'Fall' AND section.year = '2009';
SQL查询中使用视图
用下面的查询找到所有关于2009年秋季学期在Watson大楼开设的physics课程:
SELECT course_idFROM physics_fall_2009WHEREbuilding = 'Watson';
![912a6f7150011c7c6116ef1431609a7b.png](https://i-blog.csdnimg.cn/blog_migrate/8bc55aa641094ff9c2947c296cbf0604.jpeg)
定义一个视图时,数据库存储视图本身的定义,而不存储该视图的查询表达式的执行结果。一旦视图关系出现在查询中,它就被已经存储的查询表达式代替。因此,无论何时,执行这个查询,视图关系都被重新计算。
一个视图被用到定义另一个视图的表达式。定义视图physics_fall_2009_waston,列出2009年秋季学期waston大楼开设的所有physics课程的标识和房间号:
CREATE VIEW physics_fall_2009_waston AS SELECT course_id, room_number FROM physics_fall_2009 WHERE building = 'Waston';
在任何时刻,视图关系中的元组集是该时刻视图定义的查询表达式的计算结果。因此,当一个视图关系被计算并存储,一旦用于定义该视图的关系被修改,视图就会过期。为了避免这一点,视图通常这样来实现:当我们定义一个视图时,数据库系统存储视图的定义本身,而不存储定义该视图的查询表达式的执行结果。一旦视图关系出现在查询中,它就被已存储的查询表达式代替。所以,无论何时执行这个查询,视图关系都被重新计算。
但是有例外,有些数据库系统存储视图关系,如果用于定义视图的实际关系改变,视图也会跟着修改。这样的视图被称为物化视图。关于物化视图,因为涉及的点比较多,后面专门说明。
SQL视图更新
对查询而言,视图是一个很好的工具。我们有时也希望通过它们来表达更新、插入、删除,但是可能会带来很严重的困难。困难在于,用视图表达的数据库修改必须翻译为对数据库实际逻辑模型中实际关系的修改。
考虑之前创建的视图faculty,如果对faculty操作插入,可以这样写出:
INSERT INTO faculty VALUES ( '30765', 'Green', 'Music');
实际上是针对instructor的插入操作,然而为了要对instrucor执行插入,我们必须提供salary的值。所以只能通过以下解决方案来处理:
A. 拒绝插入,并返回一个错误信息
B. 向instructor关系插入元组(‘30675’,’Green’,’Music’,null)
这里只涉及一个关系instructor,如果涉及两个表、三个表,表之间又有相关的时候,就很难实现。因此,一般不允许对视图关系进行修改。不同的数据库指定了特定条件下允许更新视图关系,请参考各数据库文档。
一般来说,如果视图下列条件都满足,称这个视图为可更新的:
1) From子句中只有一个数据库关系
2) Select子句中只包含关系的属性名,不包含任何表达式、聚集或dintinct
3) 任何没有出现在select子句中的属性可以取空值,也就是说,这些属性上没有not null约束。
4) 查询中不含有group by或having子句。