继续复习巩固数据库,今天来重新梳理关于视图的相关知识点。
一、视图的概念
数据库中的视图是一个虚拟表,同真实的表一样,视图包含一系列带有名称的行和列数据,行和列数据来自定义视图查询所引用的表,并且在引用视图时动态生成。视图是从一个或者多个表中导出的,视图的行为与表非常相似,但视图是一个虚拟表。在视图中用户可以使用SELECT语句查询数据,以及使用INSERT、UPDATE和DELETE修改记录。视图可以使用户操作方便,而且可以保障数据库系统的安全。当对通过视图看到的数据进行修改时,相应的基本表的数据也要发生变化。同时,若基本表的数据发生变化,则这种变化也可以自动地反映到视图中。
视图是一个”虚表”,用大白话说,就是从已经存在的表的全部字段或数据中,挑选出来一部分字段或数据,组成另一张”并不存在的表”,这张虚表被称之”视图”。视图中的字段与对应的数据均来自已经存在的表。对于视图来说,这些已经存在的表就被称为”基表”。基表可以是一张表,也可以是多张表。视图的本质可以理解为一条查询语句,视图中显示的结果,就是这条查询语句查询出的结果。最后一句话说是一条查询语句,其实是不妥当的,应该是增删改查的语句。
简而言之,有以下几个特点:
1、视图是一个虚拟表(逻辑表);
2、视图中的行和列的数据来自一到多张物理表,也可以来源自其他视图;
3、可以通过视图进行增删改查;
4、如果通过视图进行增删改,那么物理表的数据也会随之做出同样的增删改;反之亦然。
5、视图的使用比较少,起码相对于一般SQL来说,不在一个数量级上;
6、视图是一种"虚表",所以不能与已经存在的表重名。
二、视图的作用
使用视图可以简化和定制用户对数据的需求。虽然对视图的操作最终都转换为对基本表的操作,视图看起来似乎没什么用处,但实际上,合理地使用视图会带来许多好处。
1、简化数据查询语句
采用视图机制可以使用户将注意力集中在所关心的数据上。如果这些数据来自多个基本表,或者数据部分来自基本表,另一部分来自视图,并且所用的搜索条件又比较复杂时,需要编写的SELECT语句就会很长,这时通过定义视图就可以简化客户段对数据的查询操作。定义视图可以将表与表之间复杂的连接操作和搜索条件对用户隐藏起来,用户只需简单地对一个视图进行查询即可。这在多次执行相同的数据查询操作时尤为有用。
2、便于用户能从多角度看待同一数据
采用视图机制能使不同的用户以不同的方式看待同数据,当许多不同类型的用户共享同一个数据库时,这种灵活性非常重要。
3、提高了数据的安全性
使用视图可以定制用户查看哪些数据:并屏蔽敏感数据。例如,不希望员工看到别人的工资, 就可以建立一个不包含工资项的职工视图, 然后让用户通过视图来访问表中的其他数据,而不授子他们直接访问基本表的权限,这样就在-定程度上提高了数据库数据的安全性。
4、提供了一定程度的逻辑独立性
视图在一定程度上提供了数据的逻辑独立性,因为视图对应的是数据库的外模式。
在关系数据库中, 数据库的重构是不可避免的。重构数据库的最常见方法是将一个基本表分 解成多个基本表。例如,可将学生表Suden( Sno, Sname, Ssex. Sege Sdepi )分解为sx( Sno, Same, Sage,)和SY.( Sng. Ssex. Sdepz) 两个表,这时对Sudent表的操作就变成了对sx和SY的操作,则可定义视图:
CRBATE VIEW student (Sno, Sname, sex, Sage, sdept)
AS
SELECT sx.Sno, sX.Sname, sY.Ssex, sx.SageASY,Sdept
FROM SX JOIN SY ON SX.Sno =SY.Sno
这样,尽管数据库的表结构变了,但应用程序可以不必修改,新建的视田保证了用户原来的关系,使用户的外模式未发生改变。
另外注意, 视图只能在定程度上提供数据的乏辑独立性,由于视图的更新是有条件的,因此,应用程序在修改数据时可能会因基本表结构的改变而受些影响。
三、创建视图
先看以下3张基本表
学生表
成绩表
课程表如下:
本篇文章,下文所有的SQL语句,均与这3张基本表有关联,所有数据源自以上3张基本表。后面不再重复。
CREATE [OR REPLACE] [{FORCE|NOFORCE}] VIEW 视图名(列名) AS SELECT查询 [WITH READ ONLY] /* 语法解析: 1. OR REPLACE:如果视图已经存在,则替换旧视图。 2. FORCE:即使基表不存在,也可以创建该视图,但是该视图不能正常使用,当基表创建成功后,视图才能正常使用。 3. NOFORCE:如果基表不存在,无法创建视图,该项是默认选项。 4. WITH READ ONLY:默认可以通过视图对基表执行增删改操作,但是有很多在基表上的限制
(比如:基表中某列不能为空,但是该列没有出现在视图中,则不能通过视图执行insert操作),
WITH READ ONLY说明视图是只读视图,不能通过该视图进行增删改操作。现实开发中,基本上不通过视图对表中的数据进行增删改操作。 */
3.1创建单源表视图
-- 定义单源表视图 -- 新建查询信息管理系学生的学号、姓名、性别、年龄的视图 create view IS_Student AS SELECT Sno,Sname,Ssex,Sage FROM student WHERE Sdept ="信息管理系" -- 通过刚刚创建好的视图,来尝试一下查询 -- 查询信息管理系男生的信息 select * from IS_Student WHERE Ssex = '男'
3.2创建多源表视图
-- 定义多源表视图 -- 新建 查询信息管理系选了"C001"课程的学生学号、姓名、和成绩的视图 create view V_IS_S1(Sno,Sname,Grade) AS SELECT student.Sno,Sname,Grade from student join sc on student.Sno = sc.Sno where Sdept = '信息管理系' and sc.Cno='C001'
3.3在已有的视图上定义新视图
-- 在已有的视图上定义新的视图 -- 在视图IS_Student上,新建查询信息管理系年龄小于20的学生学号、姓名、年龄的视图 CREATE VIEW IS_Student_Sage AS select Sno,Sname,Sage from IS_Student WHERE Sage < 20
3.4创建带表达式的视图
-- 定义带表达式的视图 -- 新建查询学生出生年份的视图,包括 学号、姓名、出生年份 create view V_birthyear (Sno,Sname,birthyear) AS SELECT Sno,Sname,2024-Sage from student
3.5创建含分组统计信息的视图
-- 定义含分组统计信息的视图 -- 新建一个查询每个学生的学号、平均成绩的视图 create view IS_GreAvg AS SELECT Sno,AVG(Grade) AverageGrade from sc GROUP BY Sno
四、使用视图
一般对数据的操作,包括增删改查,接下来的内容都是通过视图,建立在视图的基础上来讨论进行的,看看进一步能学习到什么不同的关键点。
4.1视图查询操作
-- 定义单源表视图 -- 新建查询信息管理系学生的学号、姓名、性别、年龄的视图 create view IS_Student AS SELECT Sno,Sname,Ssex,Sage FROM student WHERE Sdept ="信息管理系" -- 通过刚刚创建好的视图,来尝试一下查询 -- 查询信息管理系男生的信息 select * from IS_Student WHERE Ssex = '男'
4.2视图新增操作
-- 2、新增操作 新增一条记录 create view IS_Student_2 AS INSERT INTO student VALUES('0821105','王小雷','男','21','信息管理系')
那么是不是我们的插入语句有问题呢?我们换常规的普通的插入试一试。
-- 常规的向student表中插入一条数据记录 INSERT INTO student VALUES('0821105','王小雷','男','21','信息管理系')
此时,就说明有问题了。插入语句是没有问题的,但此时通过视图插入,是不可行的;因此,看来视图和基本表还是有一定的区别的。
4.3视图修改操作
-- 3、修改操作,新增一条记录 CREATE VIEW IS_Student3 AS UPDATE student SET Sage = 17 WHERE Sname = '李勇'
4.4视图删除操作
-- 4、删除操作 CREATE VIEW IS_Student4 AS DELETE from student WHERE Sname = '王小雷'
通过这几个操作我们得出了结论:
1、视图的查询操作,可以直接在客户端使用,但是增删改却是不行的;
2、视图和真实的物理表还是有一些区别的。
五、修改视图
-- 修改视图 ALTER VIEW 视图名(列名) AS SELECT语句 /* 语法格式:只需要将 CREATE 改为 ALTER */
六、删除视图
-- 修改视图 DROP VIEW 视图名
-- 定义多源表视图 -- 新建 查询信息管理系选了"C001"课程的学生学号、姓名、和成绩的视图 create view V_IS_S1(Sno,Sname,Grade) AS SELECT student.Sno,Sname,Grade from student join sc on student.Sno = sc.Sno where Sdept = '信息管理系' and sc.Cno='C001' -- 删除V_IS_S1这张视图 DROP VIEW V_IS_S1
七、不使用视图的理由
mysql对于视图的优化并不完善,这样说并不准确,准确的说,应该是mysql对于子查询的优化不是很好,而使用视图本身往往就意味着使用子查询,所以,如果我们必须使用视图时,最好将视图中的sql语句尽量优化,或者说,数据量大的时候尽量避免使用视图。
八、其他问题答疑
问题1:使用视图可以加快数据的查询速度吗?这句话对吗?为什么?
回答:不对,因为视图并没有保存数据,对视图的查询要转换成对基本表的查询,这个转换需要时间,它会降低查询效率。