视图的定义:视图是虚拟的表,只包含使用时动态检索数据的查询。(简单来说,查询比较复杂且使用频率较高的查询封装成一张随时可用的“表”)

使用视图的好处:

1.重用SQL语句

2.简化复杂SQL的操作

3.保护数据,方便用户权限管理(授予一些表中部分数据的访问权限,根据具体查询的条件限制,再授予用户此视图的查询更新等权限)

4.更改数据格式和表达方式。若是实际表中数据并不符合我们所需的,或是需要联合多列的信息等,可以用视图封装好,便于使用。

视图的本身是不包含数据的,它主要是用于我们查看多个表或是特定表中的特定部分数据。

视图的规则和限制:

1.唯一性:表名唯一。

2.创建视图需要一定的权限,用户权限可由管理员授予。

3.视图可以嵌套视图,但需要考虑查询性能问题。

4.视图不能索引,也不能有关联的触发器或默认值。

        这些操作一般都直接在视图来源的底表上做,比如做优化时,一个是针对视图查询sql本身写法的优化,一个是针对视图使用到的表进行优化,索引或是一些其他操作都在底表操作。

       ORACLE的物化视图和常规使用的视图不一样,可以直接建立索引,下边的在MYSQL8.0的测试中尝试使用常规的建立索引的方法,发现直接给视图建立索引是不可以的,需要在基表上建立索引才行。有没有其他的替代方法就比较考考验人了,目前工作中暂时没遇到。

5.视图的数据随底表的变化而变化。

6.直接对视图的更新与插入,删除等操作。一个看视图中查询语句的结构和一些函数的使用,一个看dbms软件对于视图一些限制。

实际上的限制可能会更详细一点,这部分知识需要参考数据库手册或是DBMS软件相关的一些文档。每个数据库都会存在一些差异,实际创建时,可以根据使用的数据库类型去查询,以便更深入的了解当前数据库的视图的实际使用与操作方法。

下列是在MYSQL8.0中的简单演示:

#演示环境为MYSQL8.0,本次演示是基于结构简单的单表的视图,主要传达一个初级的概念
#实际开发时,通常会是更复杂的SQL查询作为视图的语句(这本就是视图意义所在),而在使用更复杂的查询作为视图的创建语句时,就需要注意视图的更新与删除、修改等操作就会受到数据库实际上的限制,比如规定不能包含哪些函数,使用哪种算法等,这些具体的信息在你需要在某种数据库中创建视图时,可以去了解文档操作手册,在进行实际上的操做。

#创建视图
DROP VIEW IF EXISTS testview;
create view testview as 
    select * from course_history  WHERE  credit>=4
		WITH CHECK OPTION;  -- 此句是为了规范对视图进行增改操作时的限制

		 
#查询视图数据		 
SELECT * FROM testview;

#检查某个表的状态
CHECK TABLE testview;

#查询某个表结构
 DESCRIBE course_history;
 DESCRIBE testview;
 
 #查看某个表的创建语句
 SHOW CREATE VIEW testview;
 
#这个是复制查询出来的视图创建语句,可以发现和我们所创建还是有所区别的。这个符合数据库规范的定义,正常情况下我们只需要按照简短的创建语句去创建视图即可,其他的比如算法会有默认的值,如果有特殊要求,在按照下列的语法添加上即可。
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `testview` AS 
select `course_history`.`cno` AS `cno`,
`course_history`.`cname` AS `cname`,
`course_history`.`credit` AS `credit`,
`course_history`.`semester` AS `semester` 
from `course_history` 
where (`course_history`.`credit` >= 4) WITH CASCADED CHECK OPTION

#插入数据
INSERT INTO testview VALUE ('C015','测试',4,10); -- 此句符合视图中WHERE条件credit>=4,数据插入成功
INSERT INTO testview VALUE ('C015','测试',3,10); -- 此句会报错说明不符合视图的中查询的条件

#更新视图中的某条数据
UPDATE testview  SET cno ='C022'  WHERE cno='C015' ;

#删除
DELETE FROM testview WHERE cno = 'C022';

#查询数据中的基表,会发现我们对试图的操作也同步到了基表中(符合视图定义,且符合基表的数类型)
SELECT * FROM course_history;


#查看是否能在视图添加索引
ALTER table testview ADD INDEX CNOINDEX(cno);  -- 报错不是基表,不能添加

ALTER table course_history ADD INDEX CNOINDEX(cno); -- 给基表添加是没问题的
DROP INDEX CNOINDEX ON  course_history;  -- 删除索引

#查看表索引信息
SHOW INDEX FROM testview;
SHOW INDEX FROM course_history;

 使用到的测试数据表:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for course_history
-- ----------------------------
DROP TABLE IF EXISTS `course_history`;
CREATE TABLE `course_history`  (
  `cno` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '课程号',
  `cname` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '课程名',
  `credit` int(0) NULL DEFAULT NULL COMMENT '学分',
  `semester` int(0) NULL DEFAULT NULL COMMENT '开课学期',
  PRIMARY KEY (`cno`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of course_history
-- ----------------------------
INSERT INTO `course_history` VALUES ('C001', '高等数学', 4, 1);
INSERT INTO `course_history` VALUES ('C002', '大学英语', 3, 1);
INSERT INTO `course_history` VALUES ('C003', '大学英语', 3, 2);
INSERT INTO `course_history` VALUES ('C004', '计算机文化学', 2, 2);
INSERT INTO `course_history` VALUES ('C005', 'Java', 2, 3);
INSERT INTO `course_history` VALUES ('C006', '数据库基础', 4, 5);
INSERT INTO `course_history` VALUES ('C007', '数据结构', 4, 4);
INSERT INTO `course_history` VALUES ('C008', '计算机网络', 4, 4);
INSERT INTO `course_history` VALUES ('C009', '移动通信', 3, 3);
INSERT INTO `course_history` VALUES ('C010', '中国文学近代史', 5, 4);

SET FOREIGN_KEY_CHECKS = 1;