在前面的操作中,都是在逻辑模型层上,即我们假定给定的集合中的关系都是实际存储在数据库中的。
让所有用户看到整个模型是不合适的。出于安全,我们可能会向用户隐藏特定的信息数据。比如,一个职员没有权限看到教师的工资。SQL描述:
select id ,name,dept_name
from instructor;
或者是创建一个更符合用户直觉的个人化的关系集合:
-- 关于生物系在2018年春季学期所开设的所有课程的列表
SELECT course.course_id,sec_id,building,room_number
FROM course,section
WHERE (course.course_id,course.dept_name,section.semester,section.year)=(section.course_id,'biology','spring',2018);
我们可以把上面那些操作的结果存储下来,提供给用户。但是,当instructor、course和section表发生改变时,这些结果是不会改变的。
这里SQL就定义了“虚关系”,它在概念上包括查询的结果。虚关系并不预先计算并存储结果,而是在使用虚关系的时候才通过执行查询被计算出来,视图关系是在需要的时候被创建。
任何像这种不是逻辑模型的一部分,但作为虚关系对用户可见的关系称为视图(view)
1、视图定义
通式
create view 视图名 as<查询语句(query expression)>
示例对上面的对一个例子转化为视图。
CREATE VIEW faulty AS
SELECT id,name,dept_name
FROM instructor;
这个时候我们会在IDE上看到生成的view:
这是我们可以对生成的视图进行查询:
SELECT name,dept_name
FROM faulty;
视图的本质是查询表达式。
视图的实现:当我们定义一个视图是,数据库系统存储视图的定义本身,而不存储定义该视图的查询表达式的执行结果。一旦视图关系出现在查询中,他就被已存储的查询表达式代替,所以,何时执行这个查询,视图关系都被重新计算。
个人感觉吗,视图的作用有点类似于之前提到过的with子句。
2、视图更新
数据库有增删改查,对于查询,视图是很有用的,但如果在视图上进行增删改,则会带来严重的问题。例如:
insert into faulty
values('30765,'green','biology');
这个查询必须表示为对instructor的插入,因为instructor是数据库系统用于构造视图faulty的实际关系,然而,为了把一个元组插入到instructor中,还须给出salary的值。对于salary的处理有两种:
1)拒绝,返回错误信息;
2)salary设为空值。
另外,我们有这样视图:
CREATE VIEW instr_info AS
SELECT id,name,building
FROM instructor NATURAL JOIN department;
我们对它执行插入操作:
INSERT INTO instr_info
VALUES ('69876','white','Taylor');
我们假设name 和building Taylor都是不存在的。由于Taylor是不存在,那么为了使插入插入操作可执行,必行现在department插入。也就说想instructor和department关系插入元组的唯一方法是:向instructor插入(‘69876’,‘white’,null,null),并向department插入(null,‘Taylor’,null),假设插入成功,执行下面的查询操作:
select * from instructor
并不会出现预期的效果,出现的效果是
id | name | building | salary |
---|---|---|---|
69876 | white | null | null |
所以一般而言我们不对视图进行更新操作,如果真要进行更新,视图应该要满足下列的条件:
- from子句中只有一个关系
- select子句中只包含关系的属性名,不包含任何的表达式,聚集或者distinct声明
- 任何出现在select子句中的属性可以取空值,既没有not null约束。
- 查询中不函数group by 或having子句。