前言:当一个大型系统在建立时,会发现,数据库虽然可以存储海量的数据,可是一旦数据关系复杂,比如学生表(学号、姓名、年龄),学生成绩表(学号、科目、成绩),如需要姓名、科目、成绩组成关系,这样的情况我们选择创建一个新表是非常浪费资源的动作,为此,视图诞生了!
文章结构:(1)视图概述;(2)视图的操作;(3)视图使用注意点。
一、视图概述:
(1)什么是视图?
视图是基于 SQL 语句的结果集的可视化的表。
视图包含行和列,就像一个真实的表。视图中的字段就是来自一个或多个数据库中的真实的表中的字段。视图并不在数据库中以存储的数据值集形式存在,而是存在于实际引用的数据库表中,视图的构成可以是单表查询,多表联合查询,分组查询以及计算(表达式)查询等。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。
(2)视图的优点:
1)简化用户操作:
视图不仅可以简化用户对数据的理解,也可以简化他们的操作。
视图机制使用户可以将注意力集中在所关心地数据上。如果这些数据不是直接来自基本表,则可以通过定义视图,使数据库看起来结构简单、清晰,并且可以简化用户的的数据查询操作。
2)用户能以多种角度看待同一数据:
使不同的用户以不同的方式看待同一数据,当许多不同种类的用户共享同一个数据库时,这种灵活性是非常必要的。
3)对重构数据库提供了一定程度的逻辑独立性:
视图可以使应用程序和数据库表在一定程度上独立。
数据的物理独立性是指用户的应用程序不依赖于数据库的物理结构。数据的逻辑独立性是指当数据库重构造时,如增加新的关系或对原有的关系增加新的字段,用户的应用程序不会受影响。层次数据库和网状数据库一般能较好地支持数据的物理独立性,而对于逻辑独立性则不能完全的支持。
4)安全性,对机密数据提供安全保护:
通过视图用户只能查询和修改他们所能见到的数据。
(3)视图的缺点:
1)性能差:
把视图查询转化成对基本表的查询,如果这个视图是由一个复杂的多表查询所定义,那么,即使是视图的一个简单查询,sql server也要把它变成一个复杂的结合体,需要花费一定的时间。
2)修改限制:
当用户试图修改试图的某些信息时,数据库必须把它转化为对基本表的某些信息的修改,对于简单的试图来说,这是很方便的,但是,对于比较复杂的试图,可能是不可修改的。
(4)视图使用场景:
1) 权限控制的时候。当用户需要查询未授权的数据表且又需要部分数据表的部分列进行逻辑处理,不希望用户访问表中某些含敏感信息的列。
2)关键信息来源于多个复杂关联表,可以创建视图提取我们需要的信息,简化操作;
(5)视图的分类:
1)关系视图:
它属于数据库对象的一种,也就是最常见的一种关联查询;
2)内嵌视图:
它不属于任何用户,也不是对象,创建方式与普通视图完全不同,不具有可复用性,不能通过数据字典获取数据;
3)对象视图:
它是基于表对象类型的视图,特性是继承、封装等可根据需要构建对象类型封装复杂查询(官方:为了迎合对象类型而重建数据表是不实现的);
4)物化视图:
它主要用于数据库的容灾(备份),实体化的视图可存储和查询,通过DBLink连接在主数据库物化视图中复制,当主库异常备库接管实现容灾;
二、视图的操作:
准备数据:
//课程表
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`description` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `course` VALUES ('1', 'java', 'JAVA课程');
INSERT INTO `course` VALUES ('2', '数学', '数学课程');
INSERT INTO `course` VALUES ('3', '英语', '英语课程');
//学生表:
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`account` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`address` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `student` VALUES ('1', '123', '小符', '中国');
INSERT INTO `student` VALUES ('2', '456', '小张', '美国');
INSERT INTO `student` VALUES ('3', '789', '小王', '英国');
//多对多关系必须一张中间表:
DROP TABLE IF EXISTS `student_course`;
CREATE TABLE `student_course` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`studentid` bigint(20) NOT NULL,
`courseid` bigint(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
INSERT INTO `student_course` VALUES ('1', '1', '2');
INSERT INTO `student_course` VALUES ('2', '1', '3');
INSERT INTO `student_course` VALUES ('3', '2', '1');
INSERT INTO `student_course` VALUES ('4', '2', '2');
INSERT INTO `student_course` VALUES ('5', '2', '3');
INSERT INTO `student_course` VALUES ('6', '3', '2');
(1)创建视图:
1. helloworld视图:
2. 业务中的复杂视图:
先明确视图需求:我们要查询出一个人的所有课程信息,并且以一门课程一条记录显示(也就是这种复杂的需求要用视图而已)。基本SQL如下:
SELECT
uc.id AS id,
s.name AS name,
c.name AS coursename
FROM
student s
LEFT JOIN student_course uc ON (s.id = uc.studentid)
LEFT JOIN course c ON (uc.courseid = c.id)
WHERE
s.`name` = '小符'
然后创建视图:
DROP VIEW
IF EXISTS `view_student_course`;
CREATE ALGORITHM = UNDEFINED
DEFINER = `root`@`localhost`
SQL SECURITY DEFINER
VIEW `view_student_course` AS (
SELECT
uc.id AS id,
s.name AS name,
c.name AS coursename
FROM
student s
LEFT JOIN student_course uc ON (s.id = uc.studentid)
LEFT JOIN course c ON (uc.courseid = c.id)
);
测试视图:
SELECT
test.name,
test.coursename
FROM
view_student_course test
WHERE
test.name = '小符'
MySQL的视图功能拓展:
ALGORITHM=UNDEFINED:指定视图的处理算法;
DEFINER=root
@localhost
:指定视图创建者;
SQL SECURITY DEFINER:指定视图查询数据时的安全验证方式;
(2)修改视图SQL:
已经创建的视图,有时会需要修改其查询字段或查询条件
ALTER VIEW 视图名 AS SELECT 查询语句;
到头来还是要控制SQL,不过窗口话了,我们调用面向的是视图,不是面向原始数据表了。
(3)增删改视图数据:
先尝试在我们的视图上修改数据:结果如下:
update view_student_course set name='test',coursename='前端' where id=3;
因为不能在一张由多张关联表连接而成的视图上做同时修改两张表的操作;
那么,我们在视图上可以做哪些视图数据操作呢??
在这之前,我们必须明确!增删改最终都是修改到基础表。
1)视图与表是一对一关系情况:如果没有其它约束(如视图中没有的字段,在基本表中是必填字段情况),是可以进行增删改数据操作;
//注意是view_helloworld 视图
//插入
INSERT INTO view_helloworld VALUES ('5', '321', '小柱', '中国');
//更新:
UPDATE view_helloworld SET name = '小成' WHERE id = 5;
//删除
DELETE FROM view_helloworld WHERE name = '小柱';
2)视图与表是一对多关系情况:如果只修改一张表的数据,且没有其它约束(如视图中没有的字段,在基本表中是必填字段情况),是可以进行改数据操作。而且,只能做修改操作。
update view_student_course set coursename='Java' where id=1;
上面的具体是修改怎样的数据呢?我们来看一下原来的数据是这样:
执行修改语句后:可以看到,修改的都是叫数学的课程。原因是??
where id=1指向的是视图第一条记录,而视图第一条中coursename是数学,指向的是course表name叫数学的记录。也就是说最终修改的是course表的记录中name叫数学的记录,把数学改成了Java。--也就是修改了课程名称。所以,最终课程名称原来叫数学的都变成了Java。
下面这些操作是不可以的:
delete from view_student_course where id=3;
insert into view_student_course (username, coursename) VALUES('2','3');
(4)删除视图:
与删除表的语法类似:
DROP VIEW 视图名;
(5)查看视图状态:
DESCRIBE view_helloworld
分别是是字段,字段类型,允许空,索引,补充
show CREATE view view_helloworld
分别是视图名,创建语句,字符编码
三、视图使用注意点:
(1)修改操作时要非常非常小心,不然不经意间你已经修改了基本表里的多条数据;
(2)视图中的查询语句性能要调到最优;
(3)虽说上面讲到,视图有些是可以修改的。但是更多的是禁止修改视图。
对于可更新的视图,在视图中的行和基表中的行之间必须具有一对一的关系或者特殊的没有约束的一对多字段。还有一些特定的其他结构,这类结构会使得视图不可更新。
不可更改的情况如下:视图中含有以下的都不可被修改了。
(一)聚合函数(SUM(), MIN(), MAX(), COUNT()等)。
(二)DISTINCT。如下错误。
(三)GROUP BY
(四)HAVING
(五)UNION或UNION ALL
(六)位于选择列表中的子查询
(七)Join
(八)FROM子句中的不可更新视图
(九)WHERE子句中的子查询,引用FROM子句中的表。
(十)ALGORITHM = TEMPTABLE(使用临时表总会使视图成为不可更新的)。
(4)视图中虽然可以更新数据,但是有很多的限制。一般情况下,最好将视图作为查询数据的虚拟表,而不要通过视图更新数据。因为,使用视图更新数据时,如果没有全面考虑在视图中更新数据的限制,就可能会造成数据更新失败。
好了,MySQL优化笔记(七)--视图应用详解讲完了,又是一篇MySQL优化笔记,这是积累的必经一步,我会继续出这个系列文章,分享经验给大家。欢迎在下面指出错误,共同学习!!你的点赞是对我最好的支持!!!