视图是什么
视图(VIEW)是把一条 SELECT 语句存成命名对象,查询视图时 MySQL 把定义展开后执行。普通视图不存数据,只存定义,MySQL 8.0 没有物化视图。它的两个主要价值:把复杂的多表关联封装成一张「虚拟表」给调用方用;以及把权限收敛到固定列,让只该看部分字段的人拿不到完整表。代价是嵌套过深时可读性与执行计划都会恶化。
基本信息
| 语法 | CREATE [OR REPLACE] VIEW 视图名 [(列名...)] AS SELECT ... |
|---|---|
| 算法 | ALGORITHM = MERGE(与外部查询合并)或 TEMPTABLE(先物化临时表) |
| 安全上下文 | SQL SECURITY DEFINER(默认,以定义者权限执行)/ INVOKER |
| 查看定义 | SHOW CREATE VIEW 名;information_schema.views 的 VIEW_DEFINITION |
| 删除与替换 | DROP VIEW 名;CREATE OR REPLACE VIEW 原地换定义 |
典型使用场景
- 封装复杂关联:把多表 JOIN 与聚合固化成一个名字,报表与前端不必重复写长 SQL
- 收敛列级权限:只把不含手机号、身份证的列暴露给数据分析账号,原表不给 SELECT
- 兼容老接口:底层表拆表改名后,用同名视图保持旧查询语句可用,减少应用改造
- 统一口径:把「有效订单」的过滤条件写进视图,避免各处口径不一致
- 屏蔽物理细节:表分区或分表迁移期间,用视图对上层给出稳定接口
创建与使用
创建与使用
-- 汇总视图:一条语句封装聚合逻辑
CREATE OR REPLACE VIEW v_user_order_summary AS
SELECT u.id AS user_id, u.name, COUNT(o.id) AS order_cnt, IFNULL(SUM(o.amount),0) AS total
FROM users u LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id, u.name;
-- 查询视图与查表写法一致
SELECT * FROM v_user_order_summary WHERE total > 1000;
-- 确认视图定义与算法
SHOW CREATE VIEW v_user_order_summary\G
-- 权限收敛:账号只给视图权限,不给底层表权限
GRANT SELECT ON appdb.v_user_order_summary TO 'bi_ro'@'10.0.%';视图能否更新判断
| 情形 | 是否可做 INSERT/UPDATE/DELETE | 说明 |
|---|---|---|
| 单表、无聚合、无去重 | 可更新 | 一一对应底层行 |
| 含 GROUP BY / 聚合函数 | 不可更新 | 结果行与底层行无一一对应关系 |
| 含 DISTINCT / UNION | 不可更新 | 同上,无法定位被改行 |
| 含子查询在 FROM 中 | 通常不可更新 | 以实际报错为准,可先用 EXPLAIN 验证 |
| 加 WITH CHECK OPTION | 可更新但受限 | 写入行必须仍满足视图的 WHERE 条件 |
MERGE 算法把视图定义与外部查询合并后再优化,通常效率更好;TEMPTABLE 会先生成临时表,外部 WHERE 无法下推,可能突然变慢。用 EXPLAIN 对比即可看出走了哪种。
默认 SQL SECURITY DEFINER 意味着执行者按定义者权限访问底层表,这是收敛权限的常用手段,但也要求定义者账号本身权限可控,别用高权限账号随意建视图。