前言:当一个大型系统在建立时,会发现,数据库虽然可以存储海量的数据,可是一旦数据关系复杂,比如学生表(学号、姓名、年龄),学生成绩表(学号、科目、成绩),如需要姓名、科目、成绩组成关系,这样的情况我们选择创建一个新表是非常浪费资源的动作,为此,视图诞生了!
视图是基于 SQL 语句的结果集的可视化的表。
视图包含行和列,就像一个真实的表。视图中的字段就是来自一个或多个数据库中的真实的表中的字段。视图并不在数据库中以存储的数据值集形式存在,而是存在于实际引用的数据库表中,视图的构成可以是单表查询,多表联合查询,分组查询以及计算(表达式)查询等。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。
视图不仅可以简化用户对数据的理解,也可以简化他们的操作。
视图机制使用户可以将注意力集中在所关心地数据上。如果这些数据不是直接来自基本表,则可以通过定义视图,使数据库看起来结构简单、清晰,并且可以简化用户的的数据查询操作。
使不同的用户以不同的方式看待同一数据,当许多不同种类的用户共享同一个数据库时,这种灵活性是非常必要的。
视图可以使应用程序和数据库表在一定程度上独立。
数据的物理独立性是指用户的应用程序不依赖于数据库的物理结构。数据的逻辑独立性是指当数据库重构造时,如增加新的关系或对原有的关系增加新的字段,用户的应用程序不会受影响。层次数据库和网状数据库一般能较好地支持数据的物理独立性,而对于逻辑独立性则不能完全的支持。
把视图查询转化成对基本表的查询,如果这个视图是由一个复杂的多表查询所定义,那么,即使是视图的一个简单查询,sql server也要把它变成一个复杂的结合体,需要花费一定的时间。
当用户试图修改试图的某些信息时,数据库必须把它转化为对基本表的某些信息的修改,对于简单的试图来说,这是很方便的,但是,对于比较复杂的试图,可能是不可修改的。
当用户需要查询未授权的数据表且又需要部分数据表的部分列进行逻辑处理,不希望用户访问表中某些含敏感信息的列。
它属于数据库对象的一种,也就是最常见的一种关联查询;
它是基于表对象类型的视图,特性是继承、封装等可根据需要构建对象类型封装复杂查询(官方:为了迎合对象类型而重建数据表是不实现的);
它主要用于数据库的容灾(备份),实体化的视图可存储和查询,通过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');
先明确视图需求:我们要查询出一个人的所有课程信息,并且以一门课程一条记录显示(也就是这种复杂的需求要用视图而已)。基本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 = '小符'
ALGORITHM=UNDEFINED:指定视图的处理算法;
DEFINER=root
@localhost
:指定视图创建者;
SQL SECURITY DEFINER:指定视图查询数据时的安全验证方式;
已经创建的视图,有时会需要修改其查询字段或查询条件
ALTER VIEW 视图名 AS SELECT 查询语句;
到头来还是要控制SQL,不过窗口话了,我们调用面向的是视图,不是面向原始数据表了。
先尝试在我们的视图上修改数据:结果如下:
update view_student_course set name='test',coursename='前端' where id=3;
因为不能在一张由多张关联表连接而成的视图上做同时修改两张表的操作;
在这之前,我们必须明确!增删改最终都是修改到基础表。
//注意是view_helloworld 视图
//插入
INSERT INTO view_helloworld VALUES ('5', '321', '小柱', '中国');
//更新:
UPDATE view_helloworld SET name = '小成' WHERE id = 5;
//删除
DELETE FROM view_helloworld WHERE name = '小柱';
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');
DROP VIEW 视图名;
DESCRIBE view_helloworld
show CREATE view view_helloworld
(一)聚合函数(SUM(), MIN(), MAX(), COUNT()等)。
(二)DISTINCT。如下错误。
(三)GROUP BY
(四)HAVING
(五)UNION或UNION ALL
(六)位于选择列表中的子查询
(七)Join
(八)FROM子句中的不可更新视图
(九)WHERE子句中的子查询,引用FROM子句中的表。
(十)ALGORITHM = TEMPTABLE(使用临时表总会使视图成为不可更新的)。
一般情况下,最好将视图作为查询数据的虚拟表,而不要通过视图更新数据。因为,使用视图更新数据时,如果没有全面考虑在视图中更新数据的限制,就可能会造成数据更新失败。
又是一篇MySQL优化笔记,这是积累的必经一步,我会继续出这个系列文章,分享经验给大家。欢迎在下面指出错误,共同学习!!你的点赞是对我最好的支持!!!