视图的基本概念
视图是从一个或几个基本表(或者视图)导出的表。它与基本表不同,是一个虚表。
数据库只存放视图的定义,而不存放视图对应的数据,这些数据仍存放在原来的基本表中。所以基本表中的数据发生变化,从视图中查询出的数据也就随之改变了。
视图一经定义,就可以和基本表一样被查询、被删除。也可以在一个视图之上再定义新的视图,但对视图的更新(增、删、改)操作则有一定的限制。
视图的优点
视图相比基本表有以下优点:
1.视图能够简化用户的操作
视图机制用户可以将注意力集中在所关心的数据上。如果这些数据不是直接来自基本表,则可以通过定义视图,使数据库看起来结构简单、清晰,并且可以简化用户的数据查询操作。
2.视图是用户能以不同的角度看待同样的数据。
对于固定的一些基本表,我们可以给不同的用户建立不同的视图,这样不同的用户就可以看到自己需要的信息了。
3.视图对重构数据库提供了一定程度的逻辑性。
比如原来的A表被分割成了B表和C表,我们仍然可以在B表和C表的基础上构建一个视图A,而使用该数据表的程序可以不变。
4.视图能够对机密数据提供安全保护
比如说,每们课的成绩都构成了一个基本表,但是对于每个同学只可以查看自己这门课的成绩,因此可以为每个同学建立一个视图,隐藏其他同学的数据,只显示该同学自己的数据。
5.适当的利用视图可以更加清晰的表达查询
有时用现有的视图进行查询可以极大的减小查询语句的复杂程度。
说明:本文章中的用来作为示例的数据表有三个:student、course、sc 数据表具体请看:Mysql数据库中的EXISTS和NOT EXISTS
建立视图
SQL视图建立命令
CREATE VIEW [([,]…)]
AS
[WITH CHECK OPTION];
其中,子查询可以是任意复杂的SELECT语句,但通常不允许包含ORDER BY子句和DISTINCT短语(因为子查询是中间结果)。
组成视图的属性列名可以
全部省略或全部指定,如果省略,则隐含由子查询中SELECT目标列中的诸字段组成;
但在下列情况下必须明确指定视图的所有列名:
(1)某个目标列不是单纯的属性名,而是聚集函数或列表达式,或者目标列为*
(2)多表连接时选出了几个同名列作为视图的字段
(3)需要在视图中为某个列启用新的更合适的名字
RDBMS执行CREATE VIEW语句时只是把视图的定义存入数据字典,并不执行其中的SELECT语句。在对视图查询时,按视图的定义从基本表中将数据查出。
建立的视图可以简单的分为以下三类:
行列子集视图
若一个视图是从单个基本表导出的,并且只是去掉了基本表的某些行和某些列,但保留了主码,我盟称这类视图为行列子集视图
例子1.1
建立信息系学生的视图
SQL语句:
CREATE VIEW IS_Student
AS SELECT Sno, Sname, Sage FROM Student WHERE Sdept= 'IS'
本例中省略了视图IS_Student的列名,隐含了由子查询中SELECT子句中的三个列名组成。
WITH CHECK OPTION表示对视图进行UPDATE、INSERT和DELETE操作时要保证更新、插入或删除的行满足视图定义中的谓词条件(即子查询中的条件表达式)
例子1.2
建立信息系学生的视图,并要求透过该视图进行的更新操作只涉及信息系学生
SQL语句:
CREATE VIEW IS_Student
AS SELECT Sno, Sname, Sage
FROM Student
WHERE Sdept= 'IS'
WITH CHECK OPTION;
由于在定义IS_Student视图时加上了WITH CHECK OPTION子句,以后对该视图进行插入、修改和删除操作时,RDBMS会自动加上Sdept='IS'的条件:
插入操作:DBMS自动检查Sdept属性值是否为'IS'
如果不是,则拒绝该插入操作
如果没有提供Sdept属性值,则自动定义Sdept为'IS'
修改操作:DBMS自动加上Sdept= 'IS'的条件
删除操作:DBMS自动加上Sdept= 'IS'的条件
视图不仅可以建立在单个基本表上,也可以建立在多个基本表上,或者建立在基本表和视图的基础上。
例子1.3 建立信息系选修了1号课程的学生视图
CREATE VIEW IS_S1(Sno, Sname, Grade)
AS SELECT Student.Sno, Sname, Grade
FROM Student, SC
WHERE Sdept= 'IS' AND
Student.Sno=SC.Sno AND
SC.Cno= '1';
例子1.4建立信息系选修了1号课程且成绩在90分以上的学生的视图
CREATE VIEW IS_S2
AS SELECT Sno, Sname, Grade
FROM IS_S1
WHERE Grade>=90;
带表达式的视图
定义基本表时,为了减少数据库中的冗余数据,表中只存放基本数据,由基本数据经过各种计算派生出的数据一般是不存储的。
但由于视图中的数据并不实际存储,所以定义视图时可以根据应用的需要,设置一些派生属性列。
这些派生属性列由于在基本标中并不实际存在也称他们为
虚拟列,带虚拟列的视图也称为
带表达式的视图
例子2.1 定义一个反映学生出生年份的视图
CREATE VIEW BT_S(Sno, Sname, Sbirth)
AS SELECT Sno, Sname, 2000-Sage
FROM Student;
分组视图
还可以用带有聚集函数和GROUP BY子句的查询来定义视图,这种视图称为分组视图。
例子3.1将学生的学号及他的平均成绩定义为一个视图
CREATE VIEW S_G(Sno, Gavg)
AS SELECT Sno, AVG(Grade) FROM SC GROUP BY Sno;
由于AS子语句中SELECT语句语句的目标列平均成绩是通过作用聚集函数得到的,所以CREATE VIEW中必须明确定义组成S_G视图的每个属性列名,S_G是一个分组视图。
例子3.2将Student表中所有女生记录定义为一个视图
CREATE VIEW F_Student1(stdnum, name, sex, age, dept)
AS SELECT * FROM Student WHERE Ssex='女';
这里的视图F_Student1是由子查询“SELECT *”建立的,需要明确定义组成F_Student1视图的每个属性列名。
查询视图
视图定义以后,用户就可以像查询基本表一样查询视图了。
因此从用户角度看,查询视图与查询基本表相同。
不过,所有对视图的查询,都会被数据库管理软件解释成对基本数据表的查询,因为视图是在基本表的基础上抽象出来的。
例子4.1在信息系学生的视图中找出年龄小于20岁的学生
SELECT Sno, Sage
FROM IS_Student
WHERE Sage<20;
IS_Student视图的定义(视图定义例1):
CREATE VIEW IS_Student
AS SELECT Sno, Sname, Sage
FROM Student
WHERE Sdept= 'IS';
DBMS转换后的查询语句为:
SELECT Sno, Sage
FROM Student
WHERE Sdept='IS' AND Sage<20;
更新视图
更新视图是指通过视图插入、删除和修改数据。
由于视图是不实际存储数据的虚表,因此对视图的更新最终要转换为对基本表的更新。
从用户角度看,更新视图与更新基本表相同;RDBMS将之转化为对基本表的更新操作。
为防止用户通过视图对数据进行更新时,有意无意地对不属于视图范围内的基本表数据进行操作,可以在定义视图时加上WITH CHECK OPTION子句。
这样在视图上增删改数据时,RDBMS会检查视图定义中的条件,若不满足条件,则拒绝执行该操作。
例子5.1将信息系学生视图IS_Student中学号95002的学生姓名改为“刘辰”
UPDATE IS_Student
SET Sname='刘辰'
WHERE Sno='95002';
转换后的语句:
UPDATEStudent
SET Sname='刘辰'
WHERE Sno='95002' AND Sdept='IS';
在关系数据库中,并不是所有的视图都是可更新的,因为有些视图的更新不能唯一地有意义地转换成对相应基本表的更新。
一般地,
行列子集视图是可更新的,除此之外,还有一些视图理论上是可更新的,但他们的确切特征还是尚待研究的课题,还有些视图从理论上就是不可更新的。
删除视图
删除视图的语句格式:DROP VIEW ;
删除视图对生成视图的基本表没有任何影响。
删除基表时,由该基表导出的所有视图定义没有被删除,但已不能使用,必须使用DROP VIEW显式删除。
例子6.1
删除视图BT_S:
DROP VIEW BT_S;
删除视图IS_S1:
DROP VIEW IS_S1;