一、什么是视图
视图,是基于一个表或多个表或视图的逻辑表,本身不包含数据,通过它可以对表里面的数据进行查询和修改,视图基于的表称为基表。视图是存储在数据字典里的一条 Select 语句。
通俗地讲,视图就是一条 Select 语句执行后返回的结果集。所以我们在创建视图的时候,主要的工作就落在创建这条 SQL 查询语句上。
二、视图的特性及优点
1、特性:
视图是对若干张基本表的引用,一张虚表,查询语句执行的结果,不存储具体的数据(基本表数据发生了改变,视图也会跟着改变)。
可以跟基本表一样,进行增删改查操作(ps:增删改操作有条件限制);
2、优点:
● 对数据库的访问,因为视图可以有选择性的选取数据库里的一部分。
● 用户通过简单的查询可以从复杂查询中得到结果。
● 维护数据的独立性,视图可从多个表检索数据。
● 对于相同的数据可产生不同的视图。
三、视图的分类、作用及使用场合
1、分类:
视图分为简单视图和复杂视图:
简单视图只从单表里获取数据,复杂视图从多表;
简单视图不包含函数和数据组,复杂视图包含;
简单视图可以实现DML操作,复杂视图不可以。
2、作用:
方便操作,特别是查询操作,减少复杂的SQL语句,增强可读性;
更加安全,数据库授权命令不能限定到特定行和特定列,但是通过合理创建视图,可以把权限限定到行列级别;(例如我们只想给其他人展示账号和用户名,密码不展示,则可以通过视图实现。)
3、使用场合:
● 权限控制的时候,不希望用户访问表中某些敏感信息列,例如“salary(薪资)”......
● 关键信息来源于多个复杂关联表,可以创建视图提取我们需要的信息,简化操作;
四、创建视图
有如下3张表:Student(学生)、Course(课程)、学生课程中间表(Student_Course),表结构及数据如下:
1 -- ============================
2 -- Table structure for `Student`
3 -- ----------------------------
4 DROP TABLE IF EXISTS `Student`;
5 CREATE TABLE `Student` (
6 `id` bigint(20) NOT NULL AUTO_INCREMENT,
7 `account` varchar(255) NOT NULL,
8 `name` varchar(255) NOT NULL,
9 `address` varchar(255) DEFAULT NULL,
10 `others` varchar(200) DEFAULT NULL,
11 `others2` varchar(200) DEFAULT NULL,
12 PRIMARY KEY (`id`)
13 ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
14
15 -- ----------------------------
16 -- Records of Student
17 -- ----------------------------
18 INSERT INTO `Student` VALUES ('1', 'Student1', '小陈', '美国', '1', '1');
19 INSERT INTO `Student` VALUES ('2', 'Student2', '小张', '日本', '2', '2');
20 INSERT INTO `Student` VALUES ('3', 'Student3', '小王', '中国', '3', '3');
21
22 -- ============================
23 -- Table structure for `Course`
24 -- ----------------------------
25 DROP TABLE IF EXISTS `Course`;
26 CREATE TABLE `Course` (
27 `id` bigint(20) NOT NULL AUTO_INCREMENT,
28 `name` varchar(200) NOT NULL,
29 `description` varchar(500) NOT NULL,
30 PRIMARY KEY (`id`)
31 ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
32
33 -- ----------------------------
34 -- Records of Course
35 -- ----------------------------
36 INSERT INTO `Course` VALUES ('1', 'JAVA', 'JAVA课程');
37 INSERT INTO `Course` VALUES ('2', 'C++', 'C++课程');
38 INSERT INTO `Course` VALUES ('3', 'C语言', 'C语言课程');
39
40 -- ============================
41 -- Table structure for `Student_Course`
42 -- ----------------------------
43 DROP TABLE IF EXISTS `Student_Course`;
44 CREATE TABLE `Student_Course` (
45 `id` bigint(20) NOT NULL AUTO_INCREMENT,
46 `Studentid` bigint(20) NOT NULL,
47 `Courseid` bigint(20) NOT NULL,
48 PRIMARY KEY (`id`)
49 ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
50
51 -- ----------------------------
52 -- Records of Student_Course
53 -- ----------------------------
54 INSERT INTO `Student_Course` VALUES ('1', '1', '2');
55 INSERT INTO `Student_Course` VALUES ('2', '1', '3');
56 INSERT INTO `Student_Course` VALUES ('3', '2', '1');
57 INSERT INTO `Student_Course` VALUES ('4', '2', '2');
58 INSERT INTO `Student_Course` VALUES ('5', '2', '3');
59 INSERT INTO `Student_Course` VALUES ('6', '3', '2');
表数据:
这时,当我们想要查询小张上的所以课程相关信息的时候,需要这样写一条长长的SQL语句,如下:
SELECT sc.id AS id, s.name AS Studentname, c.name AS Coursename
FROM Student s
LEFT JOIN Student_Course sc
ON ((s.id = sc.Studentid))
LEFT JOIN Course c
ON ((sc.Courseid = c.id))
WHERE s.name = '小张';
但是,我们可以通过视图简化操作,例如我们创建视图 View_Student_Course,如下:
1 -- ============================
2 -- View structure for `View_Student_Course`
3 -- ----------------------------
4 DROP VIEW
5 IF EXISTS `View_Student_Course`;
6
7 CREATE ALGORITHM = UNDEFINED
8 DEFINER = `root`@`localhost`
9 SQL SECURITY DEFINER
10 VIEW `View_Student_Course` AS (
11 SELECT
12 sc.id AS id, s.name AS Studentname, c.name AS Coursename
13 FROM
14 (
15 (
16 Student s
17 LEFT JOIN Student_Course sc ON ((s.id = sc.Studentid))
18 )
19 LEFT JOIN Course c ON ((sc.Courseid = c.id))
20 )
21 );
几点说明(MySQL中的视图在标准SQL的基础之上做了扩展):
● ALGORITHM=UNDEFINED:指定视图的处理算法;
● DEFINER=`root`@`localhost`:指定视图创建者;
● SQL SECURITY DEFINER:指定视图查询数据时的安全验证方式;
创建好视图之后,我们可以直接用以下SQL语句在视图上查询小张上的所以课程相关信息,同样可以得到所需结果:
SELECT
vsc.studentname,
vsc.coursename
FROM
View_Student_Course vsc
WHERE
vsc.studentname = '小张';
三、视图的增删改
继续,我们可以尝试在视图view_user_course上做增删改数据操作,如下:
update view_student_course set studentname='test',coursename='JAVASCRIPT' where id=3;
不错所料,操作失败,信息如下:
[SQL] update view_student_course set studentname='test',coursename='JAVASCRIPT' where id=3
[Err] 1393 - Can not modify more than one base table through a join view 'demo.view_student_course'
因为不能在一张由多张关联表连接而成的视图上做同时修改两张表的操作;
那么哪些操作可以在视图上进行呢?
视图与表是一对一关系情况:如果没有其它约束(如视图中没有的字段,在基本表中是必填字段情况),是可以进行增删改数据操作;
如我们创建用户关键信息视图 view_student_keyinfo,如下:
-- ----------------------------
-- View structure for `view_student_keyinfo`
-- ----------------------------
DROP VIEW
IF EXISTS `view_student_keyinfo`;
CREATE ALGORITHM = UNDEFINED DEFINER = `root`@`localhost` SQL SECURITY DEFINER VIEW `view_student_keyinfo` AS SELECT
`u`.`id` AS `id`,
`u`.`account` AS `account`,
`u`.`name` AS `studentname`
FROM
`student` `u`;
进行增删改操作如下,操作成功(注意 student 表中的其它字段要允许为空,否则操作失败):
INSERT INTO view_student_keyinfo (account, studentname)
VALUES
('test1', 'test1');
DELETE
FROM
view_student_keyinfo
WHERE
studentname = 'test1';
UPDATE view_student_keyinfo
SET studentname = 'updatestudent'
WHERE
id = 1
视图与表是一对多关系情况:如果只修改一张表的数据,且没有其它约束(如视图中没有的字段,在基本表中是必填字段情况),是可以进行修改数据操作,如以下语句,操作成功;
update view_student_course set coursename='JAVA' where id=1;
update view_student_course set studentname='test2' where id=3;
以下操作失败:
delete from view_student_course where id=3;
insert into view_student_course(studentname, coursename) VALUES('2','3');
四、其他
视图中的查询语句性能要调到最优;
修改操作时要小心,不经意间你已经修改了基本表里的多条数据;
其它性能相关方面待实践体会...