引言
视图(View)是虚拟表,本质是存储的SELECT语句。可以像表一样查询,但不实际存储数据。
一、视图基础
1.1 什么是视图?
视图是一个虚拟表,由查询结果组成。
特点:
- 不存储数据(只存储定义)
- 基于基础表动态生成
- 可以像表一样查询
-- 创建视图
CREATE VIEW view_name AS
SELECT column1, column2
FROM table_name
WHERE condition;
-- 查询视图
SELECT * FROM view_name;
1.2 视图的作用
- 简化复杂查询:封装复杂SQL
- 提高安全性:隐藏敏感字段
- 逻辑数据独立:修改表结构不影响应用
- 权限控制:只授予视图权限
二、创建视图
2.1 基础语法
CREATE [OR REPLACE] VIEW view_name [(column_list)]
AS select_statement
[WITH CHECK OPTION];
2.2 简单视图
-- 创建用户信息视图(隐藏敏感字段)
CREATE VIEW v_user_info AS
SELECT id, name, email, created_at
FROM users;
-- 查询视图
SELECT * FROM v_user_info;
2.3 复杂视图
-- 用户订单统计视图
CREATE VIEW v_user_order_stats AS
SELECT u.id, u.name,
COUNT(o.id) AS order_count,
IFNULL(SUM(o.amount), 0) AS total_amount,
ROUND(AVG(o.amount), 2) AS avg_amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;
-- 使用视图
SELECT * FROM v_user_order_stats WHERE order_count > 5;
2.4 带条件的视图
-- 只显示有效商品
CREATE VIEW v_active_products AS
SELECT id, name, price, stock
FROM products
WHERE status = 1 AND stock > 0;
三、查看和管理视图
3.1 查看视图列表
-- 查看所有视图
SHOW FULL TABLES WHERE Table_type = 'VIEW';
-- 查看视图定义
SHOW CREATE VIEW v_user_info;
3.2 修改视图
-- 方式1:CREATE OR REPLACE
CREATE OR REPLACE VIEW v_user_info AS
SELECT id, name, email, phone, created_at
FROM users;
-- 方式2:ALTER VIEW
ALTER VIEW v_user_info AS
SELECT id, name, email, phone, created_at
FROM users;
3.3 删除视图
DROP VIEW IF EXISTS v_user_info;
四、视图的更新
4.1 可更新视图
满足以下条件的视图可以更新:
- 没有聚合函数(SUM、COUNT等)
- 没有DISTINCT
- 没有GROUP BY
- 没有HAVING
- 没有UNION
-- 可更新视图
CREATE VIEW v_users AS
SELECT id, name, email FROM users;
-- 通过视图更新数据
UPDATE v_users SET name = '张三' WHERE id = 1;
INSERT INTO v_users (name, email) VALUES ('李四', 'lisi@example.com');
DELETE FROM v_users WHERE id = 2;
4.2 WITH CHECK OPTION
确保通过视图插入/更新的数据符合视图的WHERE条件。
-- 创建只能查看价格>1000商品的视图
CREATE VIEW v_expensive_products AS
SELECT * FROM products WHERE price > 1000
WITH CHECK OPTION;
-- ✅ 成功
INSERT INTO v_expensive_products (name, price) VALUES ('商品A', 2000);
-- ❌ 失败:不符合WHERE条件
INSERT INTO v_expensive_products (name, price) VALUES ('商品B', 500);
五、视图的限制
5.1 不可更新的视图
-- 包含聚合函数
CREATE VIEW v_category_stats AS
SELECT category, COUNT(*) AS cnt
FROM products
GROUP BY category;
-- 不能UPDATE/INSERT/DELETE
-- 包含DISTINCT
CREATE VIEW v_unique_categories AS
SELECT DISTINCT category FROM products;
-- 不能UPDATE/INSERT/DELETE
-- 包含JOIN
CREATE VIEW v_order_details AS
SELECT o.*, u.name
FROM orders o
INNER JOIN users u ON o.user_id = u.id;
-- 通常不能UPDATE/INSERT/DELETE(视具体情况)
5.2 性能问题
-- ❌ 差:视图嵌套
CREATE VIEW v1 AS SELECT * FROM products WHERE price > 1000;
CREATE VIEW v2 AS SELECT * FROM v1 WHERE stock > 10;
CREATE VIEW v3 AS SELECT * FROM v2 WHERE category = '手机';
-- ✅ 好:合并为一个查询
CREATE VIEW v_filtered_products AS
SELECT * FROM products
WHERE price > 1000 AND stock > 10 AND category = '手机';
六、实战案例
案例1:隐藏敏感信息
-- 用户表包含密码、身份证等敏感信息
CREATE VIEW v_public_user_info AS
SELECT id, name, email, created_at
FROM users;
-- 应用只需查询视图
SELECT * FROM v_public_user_info;
案例2:简化复杂查询
-- 封装复杂的统计查询
CREATE VIEW v_monthly_sales AS
SELECT DATE_FORMAT(created_at, '%Y-%m') AS month,
COUNT(*) AS order_count,
SUM(amount) AS total_sales,
ROUND(AVG(amount), 2) AS avg_order_value
FROM orders
WHERE status = 'completed'
GROUP BY DATE_FORMAT(created_at, '%Y-%m');
-- 应用层简单查询
SELECT * FROM v_monthly_sales WHERE month >= '2024-01';
案例3:权限控制
-- 不同部门看到不同数据
CREATE VIEW v_sales_dept AS
SELECT * FROM orders WHERE dept = 'sales';
CREATE VIEW v_tech_dept AS
SELECT * FROM orders WHERE dept = 'tech';
-- 授予不同权限
GRANT SELECT ON v_sales_dept TO 'sales_user'@'%';
GRANT SELECT ON v_tech_dept TO 'tech_user'@'%';
七、视图 vs 临时表 vs 子查询
| 对比项 | 视图 | 临时表 | 子查询 |
|---|---|---|---|
| 存储数据 | 否 | 是 | 否 |
| 可重用 | 是 | 会话内 | 否 |
| 性能 | 取决于查询 | 好 | 取决于查询 |
| 维护性 | 好 | 中 | 差 |
选择建议:
- 需要重用:视图
- 中间结果复杂:临时表
- 一次性查询:子查询
八、总结
核心要点
- 视图:虚拟表,存储查询定义
- 作用:简化查询、提高安全性、权限控制
- 可更新:无聚合、DISTINCT、GROUP BY的简单视图
- WITH CHECK OPTION:保证更新符合WHERE条件
- 限制:性能依赖基础表,避免嵌套视图
记忆口诀
视图虚拟表一张,存储定义不存量,
简化查询提安全,权限控制把关良。
可更新视图条件,无聚合无分组样,
CHECK OPTION保条件,实战案例记心房。
本文字数:约2,400字 难度等级:⭐⭐(SQL进阶)