SQL基础⑫ | 视图篇
0 序言
本文将系统讲解数据库中视图的相关知识
,包括视图的定义
、作用
、创建
(单表、多表、基于视图创建)、查看
、更新
、修改
与删除
操作,以及视图的优缺点。
通过学习,你能够掌握视图的基本概念,理解何时及如何合理使用视图,提升数据库操作的灵活性与安全性。
1 常见的数据库对象
数据库包含多种对象,各自承担不同功能,具体如下:
1.1 表(TABLE)
是存储数据的逻辑单元
,以行和列的形式存在,列即字段,行即记录。
1.2 数据字典
是系统表,存放数据库相关信息,数据通常由数据库系统维护,程序员一般只可查看,不应修改。
1.3 约束(CONSTRAINT)
用于执行数据校验的规则,目的是保证数据的完整性。
1.4 视图(VIEW)
是一个或多个数据表里数据的逻辑显示,本身不存储数据。
1.5 索引(INDEX)
用于提高查询性能,类似书的目录。
1.6 存储过程(PROCEDURE)
用于完成一次完整的业务处理,无返回值,但可通过传出参数传递多个值给调用环境。
1.7 存储函数(FUNCTION)
用于完成一次特定的计算,具有一个返回值。
1.8 触发器(TRIGGER)
相当于事件监听器,当数据库发生特定事件后被触发,完成相应处理。
2. 视图概述
2.1 为什么使用视图
数据访问控制:可针对不同用户提供不同查询视图,限制数据可见范围,如对销售人员隐藏采购价格、对普通员工隐藏薪酬敏感字段。
简化查询:将常用查询结果集封装为视图,减少重复编写复杂查询语句的工作量。
数据格式化:可对数据进行格式化处理,方便按特定格式展示,如拼接员工姓名与部门名。
2.2 视图的理解
视图是一种虚拟表,本身不存储数据,仅占用少量内存空间,其数据来源于基表
(赖以建立的已有表)。视图的创建和删除仅影响自身
,不影响基表;但对视图数据的增删改会同步影响基表,反之亦然。
视图的数据由SELECT语句
提供,自身不保存数据,仅作为基表数据的另一种表现形式。
3. 创建视图
3.1 基本语法
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW 视图名称 [(字段列表)]AS 查询语句[WITH [CASCADED|LOCAL] CHECK OPTION]
精简版:CREATE VIEW 视图名称 AS 查询语句
3.2 创建单表视图
3.2.1 示例1:直接使用SELECT字段作为视图字段
-- 创建视图empvu80,包含80号部门员工的ID、姓氏、薪资CREATE VIEW empvu80AS SELECT employee_id, last_name, salaryFROM employeesWHERE department_id = 80;-- 查询视图SELECT * FROM empvu80;
3.2.2 示例2:指定视图字段别名
-- 创建视图emp_year_salary,包含员工姓名和年薪(含佣金)CREATE VIEW emp_year_salary (ename, year_salary)AS SELECT ename, salary*12*(1+IFNULL(commission_pct,0))FROM t_employee;
这里要注意一点:
若未指定视图字段列表,默认与SELECT语句字段列表一致;
若SELECT字段有别名,视图字段名与别名相同
。
3.3 创建多表联合视图
3.3.1 示例1:两表内连接
-- 创建视图empview,关联员工表和部门表,包含员工ID、姓名、部门名CREATE VIEW empview AS SELECT employee_id emp_id, last_name NAME, department_nameFROM employees e, departments dWHERE e.department_id = d.department_id;
3.3.2 示例2:带聚合函数的联合视图
-- 创建视图dept_sum_vu,统计各部门薪资的最小、最大、平均值CREATE VIEW dept_sum_vu (name, minsal, maxsal, avgsal)AS SELECT d.department_name, MIN(e.salary), MAX(e.salary), AVG(e.salary)FROM employees e, departments dWHERE e.department_id = d.department_id GROUP BY d.department_name;
3.3.3 示例3:数据格式化视图
-- 创建视图emp_depart,格式化员工姓名与部门名(格式:姓名(部门名))CREATE VIEW emp_departASSELECT CONCAT(last_name,\'(\',department_name,\')\') AS emp_deptFROM employees e JOIN departments dWHERE e.department_id = d.department_id;
3.4 基于视图创建视图
基于emp_dept和emp_year_salary视图创建新视图
-- 创建视图emp_dept_ysalary,包含员工姓名、部门名、年薪CREATE VIEW emp_dept_ysalaryAS SELECT emp_dept.ename, dname, year_salaryFROM emp_dept INNER JOIN emp_year_salaryON emp_dept.ename = emp_year_salary.ename;
4. 查看视图
4.1 查看数据库中的视图对象
-- 显示数据库中所有表和视图SHOW TABLES;
4.2 查看视图结构
-- 查看视图empvu80的结构DESC empvu80;-- 或DESCRIBE empvu80;
4.3 查看视图属性信息
-- 查看视图empvu80的存储引擎、版本等信息(Comment为VIEW表示是视图)SHOW TABLE STATUS LIKE \'empvu80\'\\G
4.4 查看视图详细定义
-- 查看视图empvu80的创建语句SHOW CREATE VIEW empvu80;
5. 更新视图的数据
5.1 一般情况
MySQL支持通过INSERT、UPDATE、DELETE操作视图数据,且会同步影响基表,反之亦然。
示例1:UPDATE操作
-- 修改emp_tel视图中\"孙洪亮\"的电话UPDATE emp_tel SET tel = \'13789091234\' WHERE ename = \'孙洪亮\';-- 基表t_employee中对应数据同步更新SELECT ename,tel FROM t_employee WHERE ename = \'孙洪亮\'; -- 结果:孙洪亮 13789091234
这里跟上文约束那一篇里面写到的主表跟从表,
有个示例也是效果如此。
一个表的信息变动另一个表相关联的信息也会随着更新。
示例2:DELETE操作
-- 删除emp_tel视图中\"孙洪亮\"的记录DELETE FROM emp_tel WHERE ename = \'孙洪亮\';-- 基表t_employee中对应记录同步删除SELECT ename,tel FROM t_employee WHERE ename = \'孙洪亮\'; -- 结果:空集
5.2 不可更新的视图
当视图满足以下情况时,不支持INSERT、UPDATE、DELETE操作:
- 定义时指定
ALGORITHM = TEMPTABLE
(不支持INSERT、DELETE); - 不包含基表中所有非空且无默认值的列(不支持INSERT);
SELECT语句使用JOIN联合查询
(不支持INSERT、DELETE);- 字段列表包含数学表达式或子查询(不支持INSERT,且无法UPDATE该字段);
- 使用
DISTINCT
、聚合函数
、GROUP BY
、HAVING
、UNION
等(不支持增删改); - SELECT包含子查询且引用FROM后的表(不支持增删改);
- 基于
不可更新的视图创建
; - 常量视图。
比如说:
-- 创建基于两表连接的视图emp_deptCREATE VIEW emp_deptAS SELECT ename,salary,birthday,tel,email,hiredate,dnameFROM t_employee INNER JOIN t_departmentON t_employee.did = t_department.did;-- 插入数据会失败(JOIN视图不支持INSERT)INSERT INTO emp_dept(ename,salary,birthday,tel,email,hiredate,dname)VALUES(\'张三\',15000,\'1995-01-08\',\'18201587896\',\'zs@atguigu.com\',\'2022-02-14\',\'新部门\');
这里会报错,错误内容:Can not modify more than one base table through a join view
意思就是说,你现在这个JOIN视图不支持用INSERT语法进行插入数据。
6. 修改与删除视图
6.1 修改视图
方式1:使用CREATE OR REPLACE VIEW
-- 修改empvu80视图,包含员工ID、全名(名+姓)、薪资、部门IDCREATE OR REPLACE VIEW empvu80(id_number, name, sal, department_id)AS SELECT employee_id, first_name || \' \' || last_name, salary, department_idFROM employeesWHERE department_id = 80;
这里的图片还不够直观,
补充上姓名数据会看起来更加直观,
就好比本来是张 三,一个放在lastname,一个在firstname,
然后这里的作用就是变成一个name里面存放的就是张三
。
方式2:使用ALTER VIEW
-- 修改视图salvu50的查询条件ALTER VIEW salvu50AS SELECT employee_id ID_NUMBER, last_name NAME, salary*12 ANN_SALARYFROM employeesWHERE department_id = 60; -- 原条件为department_id = 50
同理,这种方法也能实现相同的效果。
6.2 删除视图
-- 删除视图empvu80(IF EXISTS避免视图不存在时报错)DROP VIEW IF EXISTS empvu80;
说明:删除基视图会导致依赖它的视图查询失败,需手动维护。
7 小结
7.1 视图的优点
操作简单:封装复杂查询,简化开发人员对数据库的操作,无需关注基表结构与关联关系。
减少数据冗余:仅存储查询语句,不占用数据存储资源。
数据安全:限制用户访问范围,通过视图隔离用户与基表,保障数据安全。
适应需求变化:减少因基表结构变更带来的工作量。
分解复杂逻辑:将复杂查询拆分为多个视图,组合完成复杂逻辑。
7.2 视图的不足
维护成本高:基表结构变更时需同步维护视图,嵌套视图维护更复杂。
潜在隐患:视图定义可能包含重命名、复杂逻辑,降低可读性,增加系统风险。
过多视图问题:实际项目中视图过多会增加数据库维护难度。
通过本文学习,我们要掌握视图的创建、操作及应用场景,合理使用视图提升数据库操作效率与安全性。