乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 数据库基础与安装

    • MySQL 简介
    • MySQL 5.6 到 5.7 到 8.0 关键差异速查
    • 安装 MySQL 5.7
    • 连接与断开服务器
    • 创建数据库
    • 创建数据表
    • 数据库与数据表
    • 加载数据
    • 获取数据库信息
    • 批处理模式
    • SHOW 语句汇总
    • FLUSH 与 RESET 语句
    • my.cnf 核心参数
    • 字符集与排序规则
  • 第2章 SQL基础查询

    • SELECT
    • WHERE
    • ORDER BY
    • LIMIT
    • COUNT
    • 聚合函数
    • 比较运算符
    • 逻辑运算符
    • 算术运算符
    • 模式匹配
    • NULL 值处理
    • UPDATE
    • DELETE
    • REPLACE
    • SELECT INTO
  • 第3章 数据类型与运算符

    • 数值类型
    • 字符串类型
    • 日期时间类型
    • BIT 类型
    • ENUM 类型
    • SET 类型
    • JSON 类型
    • 类型转换
  • 第4章 函数与表达式

    • 字符串函数
    • 数值函数
    • 日期函数
    • 全文检索函数
  • 第5章 高级查询与子查询

    • JOIN
    • 子查询
    • UNION
    • GROUP BY
    • HAVING
    • DISTINCT
  • 第6章 表与索引

    • 数据定义语言
    • 修改表结构
    • 视图
    • 修改视图与检查选项
    • 外键
    • 索引
    • 唯一索引
    • 复合索引
    • 存储引擎对比
    • 分区表
    • 第一范式与第二范式
    • 第三范式与 BC 范式
    • 反范式设计
  • 第7章 存储过程与函数

    • 存储过程
    • 存储函数
    • 变量
    • 流程控制
    • 游标
    • 预处理语句
  • 第8章 事务与锁

    • 事务
    • 事务隔离级别
    • 锁机制
    • MVCC
    • 死锁专题分析
    • LOCK TABLES
    • XA 事务
  • 第9章 用户管理与安全

    • 用户管理
    • 权限管理
    • 角色
    • SQL 注入防范
  • 第10章 性能优化入门

    • 执行计划
    • 索引优化
    • 查询优化
    • 查询优化器提示
    • 慢查询日志
    • InnoDB 深入机制
    • InnoDB 专项优化
    • Performance Schema
    • sys Schema
  • 第11章 复制与高可用

    • 主从复制原理
    • 半同步复制配置
    • binlog 开启与 point-in-time 恢复
    • mysqldump 全库备份
    • mysqldump 单表与条件备份
    • mysqldump 恢复与导入
    • xtrabackup 全量热备
    • xtrabackup 准备与恢复
    • xtrabackup 增量与流式备份
  • 第12章 触发器与事件

    • 触发器
    • 事件调度器
  • 参考

    • MySQL 5.7 专业术语大全
    • MySQL 5.7 关键字与保留字大全

视图

导学

视图(View)是数据库中的"虚拟表"——它不存储实际数据,而是存储一条 SELECT 查询。通过视图,你可以封装复杂的查询逻辑、隐藏敏感列、简化用户权限管理。

定义

视图(View):基于 SQL 查询结果的虚拟表。视图本身不存储数据(除非使用物化视图,MySQL 5.7 不支持),每次查询视图时都会执行底层的 SELECT 语句。

核心语法

-- 创建视图
CREATE VIEW view_name AS
SELECT 列 FROM 表 WHERE 条件;

-- 查询视图(和查询表一样)
SELECT * FROM view_name WHERE ...;

-- 删除视图
DROP VIEW IF EXISTS view_name;

-- 查看视图定义
SHOW CREATE VIEW view_name;

SQL 示例

场景一:简化复杂查询

当前数据状态:创建基础表

CREATE TABLE employees (
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(20),
    dept VARCHAR(20),
    score DECIMAL(5,2)
);

CREATE TABLE scores (
    score_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_id INT,
    score DECIMAL(5,2)
);

INSERT INTO employees (emp_name, dept, score) VALUES
('大翔', '技术部', 100),
('白歌', '技术部', NULL);

INSERT INTO scores (emp_id, score) VALUES
(1, 90),
(2, 85);

SELECT * FROM employees;
emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL
SELECT * FROM scores;
score_idemp_idscore
1190.00
2285.00

操作语句:

-- 创建一个"员工成绩汇总"视图
CREATE VIEW emp_score_summary AS
SELECT
    e.emp_id,
    e.emp_name,
    e.dept,
    s.score AS exam_score
FROM employees e
JOIN scores s ON e.emp_id = s.emp_id;

-- 查询视图
SELECT * FROM emp_score_summary;

操作后数据状态:

emp_idemp_namedeptexam_score
1大翔技术部90.00
2白歌技术部85.00
-- 像查表一样使用视图,并添加额外条件
SELECT * FROM emp_score_summary WHERE dept = '技术部';
emp_idemp_namedeptexam_score
1大翔技术部90.00
2白歌技术部85.00

结果解读:视图 emp_score_summary 封装了 JOIN 的复杂逻辑。使用者无需关心底层实现,只需像查表一样 SELECT * FROM emp_score_summary。

场景二:隐藏敏感列

当前数据状态:employees 表有姓名、部门和评分信息。

操作语句:

-- 先给 employees 表添加敏感列
ALTER TABLE employees ADD phone VARCHAR(20);
ALTER TABLE employees ADD id_card VARCHAR(18);

UPDATE employees SET phone = '13800138001', id_card = '110101200001011234' WHERE emp_id = 1;
UPDATE employees SET phone = '13900139002', id_card = '110101200001021234' WHERE emp_id = 2;

-- 查看完整表数据
SELECT * FROM employees;

当前数据状态:

emp_idemp_namedeptscorephoneid_card
1大翔技术部10013800138001110101200001011234
2白歌技术部NULL13900139002110101200001021234

操作语句:

-- 创建视图,只暴露非敏感信息
CREATE VIEW emp_public AS
SELECT emp_id, emp_name, dept FROM employees;

-- 用户只能看到这三列
SELECT * FROM emp_public;

操作后数据状态:

emp_idemp_namedept
1大翔技术部
2白歌技术部

结果解读:通过视图 emp_public,用户只能看到 emp_id、emp_name、dept 三列,无法访问底层的 phone 和 id_card 敏感数据。

场景三:通过视图限制数据访问

当前数据状态:employees 表有 dept 列。

操作语句:

-- 创建一个只能查看技术部员工的视图
CREATE VIEW tech_employees AS
SELECT emp_id, emp_name, dept, score FROM employees WHERE dept = '技术部';

SELECT * FROM tech_employees;

操作后数据状态:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL

结果解读:视图 tech_employees 封装了 WHERE dept = '技术部' 这个过滤条件。即使用户执行 SELECT * FROM tech_employees,也只会看到技术部的员工。

可更新视图

某些视图支持 INSERT、UPDATE、DELETE 操作:

当前数据状态:创建基于单表的简单视图

CREATE TABLE simple_employees (
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(20),
    dept VARCHAR(20)
);

INSERT INTO simple_employees (emp_name, dept) VALUES
('大翔', '技术部'),
('白歌', '产品部');

SELECT * FROM simple_employees;
emp_idemp_namedept
1大翔技术部
2白歌产品部

操作语句:

-- 创建基于单表的视图
CREATE VIEW tech_view AS
SELECT * FROM simple_employees WHERE dept = '技术部';

-- 通过视图插入数据
INSERT INTO tech_view (emp_name, dept) VALUES ('小崔', '技术部');

SELECT * FROM simple_employees;

操作后数据状态:

emp_idemp_namedept
1大翔技术部
2白歌产品部
3小崔技术部
SELECT * FROM tech_view;
emp_idemp_namedept
1大翔技术部
3小崔技术部

结果解读:通过 tech_view 插入的数据实际上插入到了底层表 simple_employees 中。因为视图是基于单表的简单查询,所以支持 INSERT 操作。

可更新视图的限制

操作语句:

-- 尝试通过包含 JOIN 的视图插入数据
INSERT INTO emp_score_summary (emp_name, exam_score) VALUES ('测试', 100);

操作后数据状态:

ERROR 1288 (HY000): The target table emp_score_summary of the INSERT is not insertable-into

结果解读:包含 GROUP BY、JOIN、聚合函数 的视图不可更新。实际开发中,视图主要用于查询,不推荐通过视图进行数据修改。

限制条件:

  • 不能包含 GROUP BY、DISTINCT、聚合函数、UNION
  • 不能包含子查询(某些情况允许)
  • 必须是基于单表的简单查询

实际开发中,视图主要用于查询,不推荐通过视图进行数据修改。

视图的性能考量

MySQL 5.7 处理视图的两种算法:

  • MERGE:将视图定义合并到外层查询中,优化后统一执行(性能更好)
  • TEMPTABLE:将视图结果物化为临时表,再对外层查询执行(某些复杂视图必须用)

可通过 ALGORITHM = MERGE 或 ALGORITHM = TEMPTABLE 显式指定。

查看视图使用的算法

SHOW CREATE VIEW emp_score_summary;
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER
VIEW `emp_score_summary` AS
SELECT e.emp_id, e.emp_name, e.dept, s.score AS exam_score
FROM employees e JOIN scores s ON e.emp_id = s.emp_id

结果解读:ALGORITHM=UNDEFINED 表示由 MySQL 自行选择算法。对于包含 JOIN 的视图,MySQL 通常会选择 MERGE 算法,将视图定义合并到外层查询中优化执行。

常见误区

误区正解
视图存储数据不存储(MySQL 5.7 无物化视图)。每次查询都执行底层 SELECT。
视图查询比直接查表快通常一样,甚至稍慢(多一层解析)。视图的价值在于简化和安全,而非性能。
所有视图都能更新只有基于单表、无聚合/分组/DISTINCT 的简单视图才能更新。

面试考点

Q:视图和表的区别?

表存储实际数据;视图是虚拟表,基于 SELECT 查询,不存储数据(MySQL 5.7)。视图可以封装复杂查询、隐藏列、简化权限管理。

Q:视图的优点和缺点?

优点:简化复杂查询、隐藏敏感数据、统一数据访问接口。缺点:可能隐藏性能问题(复杂的视图定义让用户 unaware)、不支持物化(每次查询都重新执行)。

Q:MySQL 5.7 支持物化视图吗?

不支持。MySQL 5.7 的视图都是"虚拟视图",每次查询都执行底层 SQL。如需物化视图效果,需手动维护汇总表(如用触发器或定时任务更新)。

小结

  • 视图是虚拟表,基于 SELECT 查询定义,不存储数据
  • 用于简化查询、隐藏敏感列、控制数据访问
  • 可更新视图有严格限制,实际开发中视图主要用于查询
  • MySQL 5.7 不支持物化视图

下一章引子:视图封装了查询逻辑,存储过程则能封装更复杂的业务逻辑——包括变量、流程控制和多条 SQL 语句。

上一页
修改表结构
下一页
修改视图与检查选项