17 MySQL 视图

17 MySQL 视图
小米里的大麦MySQL 视图
1. 视图是什么
视图就是 虚拟表,本身不存数据,它只是把一条或多条 SQL 查询封装起来,同真实的表一样包含一系列带有名称的列和行数据,用它就像操作表一样,简单理解:视图就是个存好的 SELECT 语句。 举个例子:有个员工表 employees,只想经常查销售部的人,可以建个视图 sales_staff:
1 | CREATE VIEW sales_staff AS SELECT id, name, department FROM employees WHERE department = 'Sales'; |
这样一来,查 sales_staff 就只会看到销售部员工。
2. 视图的作用
- 简化复杂查询: 可以将多表关联、复杂的过滤条件封装成一个视图,用户只需查询视图即可,无需重复编写复杂的 SQL。
- 安全性: 可以通过视图限制用户访问表中的敏感列(如密码、薪资)或特定行。用户只能看到视图定义中允许的数据,起到了字段级和行级的权限控制作用。
- 逻辑独立性: 如果应用层直接通过视图获取数据,当底层表结构发生变化时(如字段名修改、表拆分),只需要修改视图定义,不用修改应用代码。
- 数据一致性: 可以强制实施特定的业务逻辑视图,确保不同用户看到的数据格式或筛选逻辑是一致的。
3. 创建视图
语法:
1 | CREATE VIEW 视图名 AS SELECT 语句; |
OR REPLACE:如果视图存在就覆盖。WITH CHECK OPTION:保证通过视图插入/更新的数据仍符合视图条件。
4. 视图的查看和使用
查看已有的视图:
1 | SELECT TABLE_NAME FROM information_schema.views WHERE TABLE_SCHEMA = '你的数据库名'; # 查某个库里有哪些视图 |
查看视图定义:
1 | SHOW CREATE VIEW 视图名; # 能看到当初写的 SELECT 语句 |
查看字段结构:
1 | DESC 视图名; |
运行视图查数据:就当它是个表,想加 WHERE、ORDER BY 随便加。
1 | SELECT * FROM 视图名; |
5. 修改视图(定义)
MySQL 里 没专门的 ALTER VIEW 改 SELECT,一般用 CREATE OR REPLACE VIEW 来改:
1 | CREATE OR REPLACE VIEW active_users AS |
1. 修改视图会不会影响基表?
- 基表(Base Table):实际存数据的表。比如
employees、users这些表才有真正的数据。- 视图(View):虚拟表,不存数据,只是一个查询包装。它像个窗口,通过它看到基表的数据或者一部分数据。
会,但有严格限制。只有“可更新视图”才允许通过视图修改基表数据。 可更新视图必须同时满足以下条件(缺一不可):
- 基于单张基表(不能 JOIN、多表)
- 视图定义中没有 DISTINCT、GROUP BY、HAVING、聚合函数(SUM/COUNT/AVG 等)、UNION/UNION ALL
- 没有 LIMIT / OFFSET
- 没有子查询出现在 FROM 子句(派生表)(但 WHERE 中的 IN/EXISTS 子查询通常允许)
- 视图的每一列都直接对应基表中的某一列(不能是表达式、常量、函数计算结果、别名计算列等)
- 没有使用 WITH 语句中的递归 CTE
满足以上条件 → 通过视图的 INSERT/UPDATE/DELETE 会直接翻译成对基表的对应操作。
2. 修改基表会影响视图吗?
会,而且是实时的、必然的。
- 数据层面:基表数据增删改,视图查询结果立刻反映最新内容(视图不存数据,只是保存的 SELECT)
- 结构层面:基表发生以下变化,视图大概率直接失效(查询时报错 ERROR 1356):
- 删除视图中用到的列
- 修改/重命名视图中用到的列名
- 改变列的数据类型(有时可以,但不保证兼容)
- 删表、改表结构导致 SELECT 无法执行
修复方式:DROP VIEW + 重新 CREATE,或用 CREATE OR REPLACE VIEW 重写。
3. WITH CHECK OPTION
WITH CHECK OPTION 的作用就是:既然通过这个视图看数据,那就不能把数据改成“自己看不见”的样子。
场景模拟:低薪员工视图
假设创建了一个视图 low_salary,专门用来管理“工资低于 5000”的员工。
1 | CREATE VIEW low_salary AS |
这个视图就像一个 “低薪员工房间”,只有工资 < 5000 的人才能住进去。
情况 1:没加 WITH CHECK OPTION(没上锁)
在这个房间里(视图里)想把员工张三的工资改成 8000。
- 执行:
UPDATE low_salary SET salary = 8000 WHERE name = '张三'; - MySQL 反应:好的,基表数据改成了 8000。
- 结果:改成功了,但是!因为张三工资变成了 8000,他不再符合“工资 < 5000”的条件,张三瞬间从这个视图里 消失 了!
- 这感觉就像自己在这个房间里给人发钱,发完之后他有钱了,直接穿墙走了,再也看不到他了。这很容易造成数据管理混乱(比如我们以为是给低薪员工涨工资,结果涨完他跑了,自己都没确认修改成功)。
情况 2:加了 WITH CHECK OPTION(上了锁)
在这个房间里想把员工张三的工资改成 8000。
- 执行:
UPDATE low_salary SET salary = 8000 WHERE name = '张三'; - MySQL 反应:等等!你要把他改成 8000?那他就不符合这个视图的条件了(8000 不小于 5000)。既然要在这个“低薪视图”里操作,就不能把人改成“非低薪”。
- 结果:直接报错!操作被拒绝,基表数据没变,张三还在视图里。
- 就像自己在房间里想给人发钱,门口保安拦住我说:“这里只接待低薪员工,如果要给他涨到 8000,请去外面(基表或其他视图)操作,别在这里改,改了他就不属于这儿了。”
6. 删除视图
1 | DROP VIEW [IF EXISTS] view_name [, view_name] ...; |
7. 视图规则和限制(小结)
视图就是个存好的 SELECT 语句,本身不存数据。简单视图能增删改(基表会跟着变),但复杂视图(带 JOIN、GROUP BY、聚合函数这些)只能查不能改。视图里列名不能重复,也不能搞循环依赖(A 视图用 B 视图,B 视图又用 A 视图)。基表要是删了列或者改了列名,视图直接报错。想限制通过视图改数据时别改出视图范围,就加个 WITH CHECK OPTION。














