本系列可作为数据库学习系列的笔记,文中提到的一些练习的代码,小编会将代码复制下来,大家复制下来就可以练习了,方便大家学习。
点赞关注不迷路!您的点赞、关注和收藏是对小编最大的支持和鼓励!
系列文章目录
目录
目录
[1. 简化复杂SQL](#1. 简化复杂SQL)
[2. 提高安全性](#2. 提高安全性)
[3. 提高可维护性](#3. 提高可维护性)
[4. 提高可读性](#4. 提高可读性)
[3.1 创建数据库](#3.1 创建数据库)
[3.2 创建表结构](#3.2 创建表结构)
[3.3 插入测试数据](#3.3 插入测试数据)
[绝对是!而且是视图 #1 最经典用途!](#1 最经典用途!)
[使用 GROUP BY](#使用 GROUP BY)
[使用 DISTINCT](#使用 DISTINCT)
[使用 UNION](#使用 UNION)
前言
在学习 MySQL 的过程中,很多同学都会接触到一个重要对象------视图(View)。
刚开始学习时,大多数人都会认为:
视图不就是把 SQL 保存起来吗?
事实上,视图远不止这么简单。
在实际企业项目中:
-
ERP系统
-
OA办公系统
-
CRM客户管理系统
-
电商后台
-
BI数据报表系统
都会大量使用视图。
视图不仅能够简化复杂查询,还能实现:
-
数据权限控制
-
隐藏敏感字段
-
降低系统耦合度
-
统一业务查询逻辑
本文将从零开始,通过完整案例带你掌握:
✅ 创建视图
✅ 查询视图
✅ 修改视图
✅ 删除视图
✅ 不可更新视图
✅ 企业项目中的真实应用
并提供完整数据库脚本和练习题,让初学者边学边练。
一、什么是视图(View)
官方定义:
视图(View)是基于一个或多个表查询结果构成的虚拟表。
特点:
-
不存储数据
-
存储查询逻辑
-
查询时实时访问底层表
理解图:
真实表
↓
SQL查询
↓
视图(View)
↓
用户访问
例如:
学生表:
| id | name |
|---|---|
| 1 | 张三 |
| 2 | 李四 |
成绩表:
| id | student_id | score |
|---|---|---|
| 1 | 1 | 90 |
| 2 | 2 | 85 |
如果经常需要查询:
学生姓名 + 成绩
可以创建视图:
sql
CREATE VIEW v_student_score AS
SELECT
s.name,
sc.score
FROM student s
JOIN score sc
ON s.id=sc.student_id;
以后直接:
sql
SELECT * FROM v_student_score;
即可获得结果。
也可以查看视图定义
sql
SHOW CREATE VIEW v_student_score;
二、为什么要使用视图
1. 简化复杂SQL
例如查询:
-
学生
-
班级
-
课程
-
成绩
需要四表连接:
sql
SELECT
s.name,
c.name,
co.name,
sc.score
FROM student s
JOIN class c
ON s.class_id=c.id
JOIN score sc
ON s.id=sc.student_id
JOIN course co
ON sc.course_id=co.id;
sql
SELECT
s.name AS student_name,
c.name AS class_name,
co.name AS course_name,
sc.score
FROM student s, class c, course co, score sc
WHERE s.class_id=c.id AND s.id=sc.student_id AND sc.course_id=co.id;
SQL已经比较长。
如果以后变成:
学生
班级
课程
教师
院系
成绩
学期
七八张表关联时,SQL会越来越复杂。
视图可以将这些逻辑封装起来。
2. 提高安全性
例如用户表:
sql
CREATE TABLE user_account(
id INT,
username VARCHAR(50),
password VARCHAR(100),
phone VARCHAR(20)
);
普通员工不能看到密码。
创建视图:
sql
CREATE VIEW v_user_public AS
SELECT
username,
phone
FROM user_account;
查询:
sql
SELECT * FROM v_user_public;
即可隐藏密码字段。
3. 提高可维护性
如果底层表结构发生变化:
sql
name
改为:
sql
student_name
只需要修改视图即可。
应用程序无需修改。
4. 提高可读性
通过视图可以统一字段名称:
sql
student_name
class_name
course_name
比多个:
sql
name
name
name
更容易理解。
三、实验环境准备
3.1 创建数据库
sql
DROP DATABASE IF EXISTS view_demo;
CREATE DATABASE view_demo
DEFAULT CHARACTER SET utf8mb4;
USE view_demo;
验证:
sql
SHOW DATABASES;
3.2 创建表结构
班级表
sql
CREATE TABLE class (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL
);
学生表
sql
CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
sno VARCHAR(30) NOT NULL UNIQUE,
age INT,
gender VARCHAR(10),
enroll_date DATE,
class_id INT
);
课程表
sql
CREATE TABLE course (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL
);
成绩表
sql
CREATE TABLE score (
id INT PRIMARY KEY AUTO_INCREMENT,
student_id INT,
course_id INT,
score DECIMAL(5,1)
);
用户表
sql
CREATE TABLE user_account (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
password VARCHAR(100),
phone VARCHAR(20),
email VARCHAR(100)
);
查看所有表:
sql
SHOW TABLES;
结果:
sql
class
student
course
score
user_account
3.3 插入测试数据
班级数据
sql
INSERT INTO class(name) VALUES
('Java开发一班'),
('Python开发班');
学生数据
sql
INSERT INTO student
(name,sno,age,gender,enroll_date,class_id)
VALUES
('唐三藏','S001',30,'男','2024-09-01',1),
('孙悟空','S002',25,'男','2024-09-01',1),
('猪八戒','S003',28,'男','2024-09-01',2);
课程数据
sql
INSERT INTO course(name)
VALUES
('Java'),
('MySQL'),
('Linux');
成绩数据
sql
INSERT INTO score
(student_id,course_id,score)
VALUES
(1,1,95),
(1,2,88),
(1,3,90),
(2,1,99),
(2,2,92),
(2,3,85),
(3,1,75),
(3,2,80),
(3,3,45);
用户数据
sql
INSERT INTO user_account
(username,password,phone,email)
VALUES
('admin','123456',
'13800000001',
'admin@test.com');
四、不使用视图进行查询
查询学生成绩:
sql
SELECT
s.name,
c.name,
co.name,
sc.score
FROM student s
JOIN class c
ON s.class_id=c.id
JOIN score sc
ON s.id=sc.student_id
JOIN course co
ON sc.course_id=co.id;
结果:
| 学生 | 班级 | 课程 | 成绩 |
|---|---|---|---|
| 唐三藏 | Java开发一班 | Java | 95 |
| 唐三藏 | Java开发一班 | MySQL | 88 |
| 孙悟空 | Java开发一班 | Java | 99 |
虽然结果正确,但 SQL 比较复杂。
五、创建第一个视图
sql
CREATE VIEW v_student_score AS
SELECT
s.id AS student_id,
s.name AS student_name,
c.name AS class_name,
co.name AS course_name,
sc.score
FROM student s
JOIN class c
ON s.class_id=c.id
JOIN score sc
ON s.id=sc.student_id
JOIN course co
ON sc.course_id=co.id;
创建视图时,指定列名:
sql
CREATE VIEW v_student_score (
student_id,
student_name,
class_name,
course_name,
score
) AS
SELECT
s.id,
s.name,
c.name,
co.name,
sc.score
FROM student s
JOIN class c
ON s.class_id = c.id
JOIN score sc
ON s.id = sc.student_id
JOIN course co
ON sc.course_id = co.id;
查看数据库对象:
sql
SHOW FULL TABLES;
结果:
sql
v_student_score VIEW
说明:
sql
VIEW ≠ TABLE
视图不是普通表。
六、查询视图
sql
SELECT * FROM v_student_score;
结果:
| student_name | class_name | course_name | score |
|---|---|---|---|
| 唐三藏 | Java开发一班 | Java | 95 |
条件查询
查询所有 Java 成绩:
SELECT *
FROM v_student_score
WHERE course_name='Java';
排序查询
SELECT *
FROM v_student_score
ORDER BY score DESC;
七、字段重命名(Alias)
原始SQL:
SELECT
s.name,
c.name,
co.name
结果会出现:
name
name
name
难以区分。
解决:
sql
SELECT
s.name AS student_name,
c.name AS class_name,
co.name AS course_name;
视图中经常使用别名提高可读性。
八、使用视图隐藏敏感字段
创建视图:
sql
CREATE VIEW v_user_public AS
SELECT
username,
phone,
email
FROM user_account;
查询:
sql
SELECT * FROM v_user_public;
结果:
| username | phone | |
|---|---|---|
| admin | 13800000001 | admin@test.com |
密码字段已被隐藏。
这是不是视图最常用的手段?
绝对是!而且是视图 #1 最经典用途!
视图在企业里90% 的场景就是干这件事:
- 隐藏敏感字段(密码、身份证、余额)
- 只暴露可以公开的字段
- 不用创建新表!不用复制数据! 完全虚拟
九、统计总分视图
创建总分视图:
sql
CREATE VIEW v_student_total_score AS
SELECT
s.id,
s.name,
SUM(sc.score) AS total_score
FROM student s
JOIN score sc
ON s.id=sc.student_id
GROUP BY s.id;
查询:
sql
SELECT * FROM v_student_total_score;
结果:
| 姓名 | 总分 |
|---|---|
| 唐三藏 | 273 |
| 孙悟空 | 276 |
| 猪八戒 | 200 |
十、视图与真实表的关系
很多人认为:
视图 = 数据副本
这是错误的。
实际上:
视图 ≠ 数据副本
视图只是 SQL。
修改真实表:
sql
UPDATE score
SET score=100
WHERE student_id=1
AND course_id=1;
查询视图:
sql
SELECT *
FROM v_student_score
WHERE student_id=1;
发现:
95 → 100
自动同步。
说明视图不存储数据。
十一、通过视图修改数据
创建可更新视图:
sql
CREATE VIEW v_score_update AS
SELECT
id,
student_id,
course_id,
score
FROM score;
更新:
sql
UPDATE v_score_update
SET score=99
WHERE id=1;
查看真实表:
sql
SELECT * FROM score;
发现:
真实表数据同步更新
十二、哪些视图不能更新
以下视图不能执行 UPDATE。
使用聚合函数
SUM()
COUNT()
AVG()
MAX()
MIN()
例如:
sql
CREATE VIEW v_total AS
SELECT
SUM(score)
FROM score;
不能更新。
使用 GROUP BY
GROUP BY
不能更新。
使用 DISTINCT
sql
SELECT DISTINCT name
不能更新。
使用 UNION
UNION
UNION ALL
不能更新。
使用子查询
SELECT
(
SELECT ...
)
不能更新。
十三、删除视图
语法:
sql
DROP VIEW 视图名;
例如:
sql
DROP VIEW v_student_score;
注意:
删除视图不会删除数据。
十四、企业项目中的真实应用
ERP系统
采购订单汇总视图:
sql
v_purchase_order
封装:
-
供应商
-
采购单
-
到货状态
-
付款状态
OA系统
员工信息视图:
v_employee_public
隐藏:
-
身份证
-
工资
-
银行卡
BI报表
销售统计视图:
v_sales_report
封装:
SUM()
GROUP BY
报表直接查询即可。
十五、视图的优点
视图之所以在企业项目中被广泛使用,主要是因为它具备以下四大优势。
1. 简单性 ------ 简化复杂查询
假设需要查询:
- 学生姓名
- 班级名称
- 课程名称
- 成绩
使用真实表查询:
SELECT
s.name AS student_name,
c.name AS class_name,
co.name AS course_name,
sc.score
FROM student s
JOIN class c
ON s.class_id = c.id
JOIN score sc
ON s.id = sc.student_id
JOIN course co
ON sc.course_id = co.id;
随着业务复杂度增加:
学生表
班级表
课程表
教师表
院系表
成绩表
可能需要关联 5~10 张表。
SQL 会越来越长。
此时创建视图:
CREATE VIEW v_student_score AS
SELECT
s.name AS student_name,
c.name AS class_name,
co.name AS course_name,
sc.score
FROM student s
JOIN class c
ON s.class_id = c.id
JOIN score sc
ON s.id = sc.student_id
JOIN course co
ON sc.course_id = co.id;
以后只需:
SELECT * FROM v_student_score;
即可获得结果。
优势
复杂SQL → 简单查询
降低开发难度,提高代码可读性。
2. 安全性 ------ 隐藏敏感数据
在实际项目中,很多表都包含敏感信息。
例如用户表:
CREATE TABLE user_account(
id INT,
username VARCHAR(50),
password VARCHAR(100),
phone VARCHAR(20)
);
如果直接开放查询:
SELECT * FROM user_account;
用户可以看到:
用户名
密码
手机号
存在安全风险。
创建视图:
CREATE VIEW v_user_public AS
SELECT
username,
phone
FROM user_account;
查询:
SELECT * FROM v_user_public;
结果:
用户名
手机号
密码字段被隐藏。
优势
隐藏敏感字段
控制数据访问权限
提高系统安全性
3. 逻辑数据独立性 ------ 降低系统耦合
假设系统最初设计:
student.name
应用程序大量使用:
SELECT name FROM student;
后来需求变化:
name
↓
student_name
如果直接访问表:
所有程序都要修改
工作量巨大。
此时可以通过视图进行适配:
CREATE VIEW v_student AS
SELECT
student_name AS name
FROM student;
应用程序仍然执行:
SELECT name FROM v_student;
无需修改代码。
优势
数据库结构变化
↓
修改视图
↓
应用程序无需修改
实现数据库与应用程序解耦。
4. 重命名列 ------ 提高可读性
例如:
SELECT
s.name,
c.name,
co.name
FROM ...
结果:
name
name
name
很难判断:
哪个是学生名
哪个是班级名
哪个是课程名
创建视图时
CREATE VIEW v_student_score AS
SELECT
s.name AS student_name,
c.name AS class_name,
co.name AS course_name,
sc.score
FROM ...
查询结果:
| student_name | class_name | course_name | score |
|---|---|---|---|
| 唐三藏 | Java开发一班 | Java | 95 |
字段含义一目了然。
优势
增强数据可读性
统一字段命名规范
提高维护效率
四大优点总结
| 优点 | 作用 | 典型应用 |
|---|---|---|
| 简单性 | 简化复杂SQL | 多表连接查询 |
| 安全性 | 隐藏敏感字段 | 用户权限控制 |
| 逻辑数据独立性 | 降低系统耦合 | 数据库升级 |
| 重命名列 | 提高可读性 | 数据展示层 |
十六、课后练习
练习1
创建一个视图:
显示学生姓名和班级名称
参考答案:
sql
CREATE VIEW v_student_class AS
SELECT
s.name,
c.name
FROM student s
JOIN class c
ON s.class_id=c.id;
练习2
创建一个视图:
显示每门课程平均分
参考答案:
sql
CREATE VIEW v_course_avg AS
SELECT
course_id,
AVG(score) AS avg_score
FROM score
GROUP BY course_id;
练习3
查询总分最高学生
参考答案:
sql
SELECT *
FROM v_student_total_score
ORDER BY total_score DESC
LIMIT 1;
练习4
查询 Java 成绩高于90分的学生
参考答案:
sql
SELECT *
FROM v_student_score
WHERE course_name='Java'
AND score>90;
练习5
统计每个班级平均成绩
参考答案:
sql
CREATE VIEW v_class_avg_score AS
SELECT
c.name,
AVG(sc.score) avg_score
FROM class c
JOIN student s
ON c.id=s.class_id
JOIN score sc
ON s.id=sc.student_id
GROUP BY c.id;
十七、总结
本文从零开始介绍了 MySQL 视图的完整使用流程:
✔ 创建数据库
✔ 创建表
✔ 插入测试数据
✔ 创建视图
✔ 查询视图
✔ 更新视图
✔ 删除视图
✔ 不可更新视图
✔ 企业应用场景
✔ 实战练习题
记住一句话:
视图本质上是保存起来的 SQL 查询,它不存储数据,而是提供了一种更加安全、简洁、可维护的数据访问方式。
掌握视图后,你已经具备了企业级数据库开发中非常重要的一项技能。后续学习存储过程、触发器、索引优化和权限管理时,视图也会经常出现。祝你学习顺利! 🚀

总结
以上就是今天要讲的内容,本文简单记录了数据库学习内容,仅作为一份简单的笔记使用,大家根据注释理解,您的点赞关注收藏就是对小编最大的鼓励!