17 MySQL 视图

🦄 个人主页 : 小米里的大麦-CSDN博客

🎏 所属专栏 : MySQL_小米里的大麦的博客-CSDN博客

🎁 GitHub主页 : 小米里的大麦的 GitHub

文章目录

  • [MySQL 视图](#MySQL 视图)
    • [1. 视图是什么](#1. 视图是什么)
    • [2. 视图的作用](#2. 视图的作用)
    • [3. 创建视图](#3. 创建视图)
    • [4. 视图的查看和使用](#4. 视图的查看和使用)
    • [5. 修改视图(定义)](#5. 修改视图(定义))
      • [1. 修改视图会不会影响基表?](#1. 修改视图会不会影响基表?)
      • [2. 修改基表会影响视图吗?](#2. 修改基表会影响视图吗?)
      • [3. WITH CHECK OPTION](#3. WITH CHECK OPTION)
        • 场景模拟:低薪员工视图
        • [情况 1:没加 `WITH CHECK OPTION`(没上锁)](#情况 1:没加 WITH CHECK OPTION(没上锁))
        • [情况 2:加了 `WITH CHECK OPTION`(上了锁)](#情况 2:加了 WITH CHECK OPTION(上了锁))
    • [6. 删除视图](#6. 删除视图)
    • [7. 视图规则和限制(小结)](#7. 视图规则和限制(小结))
    • 共勉

MySQL 视图

1. 视图是什么

视图就是 虚拟表 ,本身不存数据,它只是把一条或多条 SQL 查询封装起来,同真实的表一样包含一系列带有名称的列和行数据,用它就像操作表一样,简单理解:视图就是个存好的 SELECT 语句。 举个例子:有个员工表 employees,只想经常查销售部的人,可以建个视图 sales_staff:

sql 复制代码
CREATE VIEW sales_staff AS SELECT id, name, department FROM employees WHERE department = 'Sales';

这样一来,查 sales_staff 就只会看到销售部员工。

2. 视图的作用

  1. 简化复杂查询: 可以将多表关联、复杂的过滤条件封装成一个视图,用户只需查询视图即可,无需重复编写复杂的 SQL。
  2. 安全性: 可以通过视图限制用户访问表中的敏感列(如密码、薪资)或特定行。用户只能看到视图定义中允许的数据,起到了字段级和行级的权限控制作用。
  3. 逻辑独立性: 如果应用层直接通过视图获取数据,当底层表结构发生变化时(如字段名修改、表拆分),只需要修改视图定义,不用修改应用代码。
  4. 数据一致性: 可以强制实施特定的业务逻辑视图,确保不同用户看到的数据格式或筛选逻辑是一致的。

3. 创建视图

语法:

sql 复制代码
CREATE VIEW 视图名 AS SELECT 语句;
CREATE [OR REPLACE] VIEW 视图名 [(列名列表)] AS SELECT ... [WITH [CASCADED | LOCAL] CHECK OPTION];

# 例1:
CREATE VIEW active_users AS SELECT id, name FROM users WHERE status = 'active' WITH CHECK OPTION;
# 例2:
CREATE VIEW v_dept_emp_cross AS
SELECT
  d.deptno AS d_deptno, d.dname, d.loc,
  e.empno, e.ename, e.job, e.mgr, e.hiredate, e.sal, e.comm, e.deptno AS e_deptno
FROM dept d, emp e;
  • OR REPLACE:如果视图存在就覆盖。
  • WITH CHECK OPTION:保证通过视图插入/更新的数据仍符合视图条件。

4. 视图的查看和使用

查看已有的视图:

sql 复制代码
SELECT TABLE_NAME FROM information_schema.views WHERE TABLE_SCHEMA = '你的数据库名';	# 查某个库里有哪些视图
mysql> SHOW FULL TABLES WHERE TABLE_TYPE = 'VIEW';	# 注意:先 USE 库名; 选对数据库
+--------------------------+------------+
| Tables_in_Compound_query | Table_type |
+--------------------------+------------+
| v_dept_emp_cross         | VIEW       |
+--------------------------+------------+

查看视图定义:

sql 复制代码
SHOW CREATE VIEW 视图名;		# 能看到当初写的 SELECT 语句
mysql> show create view v_dept_emp_cross;

查看字段结构:

sql 复制代码
DESC 视图名;
mysql> desc v_dept_emp_cross;

运行视图查数据:就当它是个表,想加 WHERE、ORDER BY 随便加。

sql 复制代码
SELECT * FROM 视图名;
mysql> SELECT * FROM v_dept_emp_cross;

5. 修改视图(定义)

MySQL 里 没专门的 ALTER VIEW 改 SELECT ,一般用 CREATE OR REPLACE VIEW 来改:

sql 复制代码
CREATE OR REPLACE VIEW active_users AS
SELECT ...
FROM users WHERE status = 'active';

mysql> CREATE OR REPLACE VIEW v_dept_emp_cross AS
    -> SELECT
    ->   d.deptno AS d_deptno,
    ->   d.dname,
    ->   d.loc,
    ->   e.empno,
    ->   e.ename,
    ->   e.job,
    ->   e.mgr,
    ->   e.hiredate,
    ->   e.sal,
    ->   e.comm,
    ->   e.deptno AS e_deptno
    -> FROM dept d
    -> JOIN emp e ON d.deptno = e.deptno;

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"的员工。

sql 复制代码
CREATE VIEW low_salary AS
SELECT * FROM employees WHERE salary < 5000
WITH CHECK OPTION; # 注意这句,这就是"安全锁"

这个视图就像一个 "低薪员工房间",只有工资 < 5000 的人才能住进去。

情况 1:没加 WITH CHECK OPTION(没上锁)

在这个房间里(视图里)想把员工张三的工资改成 8000。

  1. 执行 :UPDATE low_salary SET salary = 8000 WHERE name = '张三';
  2. MySQL 反应:好的,基表数据改成了 8000。
  3. 结果 :改成功了,但是 !因为张三工资变成了 8000,他不再符合"工资 < 5000"的条件,张三瞬间从这个视图里 消失 了!
  4. 这感觉就像自己在这个房间里给人发钱,发完之后他有钱了,直接穿墙走了,再也看不到他了。这很容易造成数据管理混乱(比如我们以为是给低薪员工涨工资,结果涨完他跑了,自己都没确认修改成功)。
情况 2:加了 WITH CHECK OPTION(上了锁)

在这个房间里想把员工张三的工资改成 8000。

  1. 执行 :UPDATE low_salary SET salary = 8000 WHERE name = '张三';
  2. MySQL 反应:等等!你要把他改成 8000?那他就不符合这个视图的条件了(8000 不小于 5000)。既然要在这个"低薪视图"里操作,就不能把人改成"非低薪"。
  3. 结果 :直接报错!操作被拒绝,基表数据没变,张三还在视图里。
  4. 就像自己在房间里想给人发钱,门口保安拦住我说:"这里只接待低薪员工,如果要给他涨到 8000,请去外面(基表或其他视图)操作,别在这里改,改了他就不属于这儿了。"

6. 删除视图

sql 复制代码
DROP VIEW [IF EXISTS] view_name [, view_name] ...;

mysql> drop view v_dept_emp_cross;
mysql> SHOW FULL TABLES WHERE TABLE_TYPE = 'VIEW';
Empty set (0.00 sec)

7. 视图规则和限制(小结)

视图就是个存好的 SELECT 语句,本身不存数据。简单视图能增删改(基表会跟着变),但复杂视图(带 JOIN、GROUP BY、聚合函数这些)只能查不能改。视图里列名不能重复,也不能搞循环依赖(A 视图用 B 视图,B 视图又用 A 视图)。基表要是删了列或者改了列名,视图直接报错。想限制通过视图改数据时别改出视图范围,就加个 WITH CHECK OPTION。

共勉

相关推荐
ss2731 小时前
PG实战笔记 | 07 PostgreSQL常见编译项及其作用
数据库·笔记·postgresql
川石课堂软件测试1 小时前
自动化测试|持续集成Git使用详解
git·python·jmeter·mysql·ci/cd·容器·kubernetes
丨白色风车丨1 小时前
LangChain 1.0 核心用法速查:创建模型、创建 Agent、调用
数据库·langchain
临床数据科学和人工智能兴趣组1 小时前
正则表达式的基础语法的常用字符类
数据库·r语言·r语言-4.2.1·临床研究·临床试验
鱼很腾apoc1 小时前
【MySQL】 第2期 查询与函数系统详解:从基础 CRUD 到复合多表查询
linux·数据库·学习·mysql·dml
前端 贾公子2 小时前
LangGraph == 图的状态(State)管理 (下)
运维·服务器·数据库
老男孩游戏时光2 小时前
MySQL锁机制详解,行锁表锁间隙锁到底怎么回事
mysql
zlwool2 小时前
机械行业ERP与进销存的合规选型边界
数据库·erp
梦想的颜色2 小时前
【AI速览】RAG 向量数据库选型:Milvus、Chroma、Qdrant、PGVector 全维度横向对比
数据库·milvus·chroma·rag·pgvector·向量库·qdrant