MariaDB视图 #
一、视图概述 #
1.1 什么是视图 #
text
视图概念
├── 虚拟表
│ └── 不存储数据,存储查询定义
├── 简化查询
│ └── 封装复杂查询
├── 安全性
│ └── 限制数据访问
└── 独立性
└── 屏蔽表结构变化
视图特点
├── 不占用存储空间(只存储定义)
├── 动态生成数据
├── 可以像表一样查询
└── 可以嵌套使用
1.2 视图用途 #
| 用途 | 说明 |
|---|---|
| 简化查询 | 封装复杂查询 |
| 数据安全 | 限制列和行访问 |
| 数据独立 | 屏蔽底层表变化 |
| 兼容性 | 提供兼容的接口 |
二、创建视图 #
2.1 基本语法 #
sql
CREATE VIEW view_name AS
SELECT statement;
2.2 创建示例 #
sql
-- 创建简单视图
CREATE VIEW user_emails AS
SELECT id, name, email FROM users;
-- 使用视图
SELECT * FROM user_emails;
-- 创建复杂视图
CREATE VIEW user_order_summary AS
SELECT
u.id,
u.name,
COUNT(o.id) AS order_count,
COALESCE(SUM(o.amount), 0) AS total_amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;
-- 使用视图
SELECT * FROM user_order_summary WHERE order_count > 0;
2.3 指定列名 #
sql
-- 创建时指定列名
CREATE VIEW user_info (user_id, user_name, user_email) AS
SELECT id, name, email FROM users;
SELECT user_id, user_name FROM user_info;
2.4 使用WITH CHECK OPTION #
sql
-- WITH CHECK OPTION:确保通过视图修改的数据仍然满足视图条件
CREATE VIEW active_users AS
SELECT id, name, email, status FROM users WHERE status = 1
WITH CHECK OPTION;
-- 插入数据(status必须为1)
INSERT INTO active_users (name, email, status) VALUES ('Test', 'test@example.com', 1); -- OK
INSERT INTO active_users (name, email, status) VALUES ('Test2', 'test2@example.com', 0); -- 错误
-- 更新数据(不能将status改为0)
UPDATE active_users SET status = 0 WHERE id = 1; -- 错误
2.5 使用OR REPLACE #
sql
-- OR REPLACE:如果视图存在则替换
CREATE OR REPLACE VIEW user_emails AS
SELECT id, name, email, status FROM users;
三、查看视图 #
3.1 SHOW CREATE VIEW #
sql
-- 查看视图定义
SHOW CREATE VIEW user_emails;
-- 结果
+-------------+-----------------------------------------------------------------------------------+
| View | Create View |
+-------------+-----------------------------------------------------------------------------------+
| user_emails | CREATE VIEW `user_emails` AS select `users`.`id`,`users`.`name`,`users`.`email` |
| | from `users` |
+-------------+-----------------------------------------------------------------------------------+
3.2 information_schema #
sql
-- 从information_schema查询
SELECT
table_name,
view_definition,
check_option,
is_updatable
FROM information_schema.views
WHERE table_schema = 'mydb';
-- 查看所有视图
SELECT table_name FROM information_schema.views WHERE table_schema = DATABASE();
3.3 DESC视图 #
sql
-- 查看视图结构
DESC user_emails;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int | NO | | 0 | |
| name | varchar(50) | YES | | NULL | |
| email | varchar(100) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
四、使用视图 #
4.1 查询视图 #
sql
-- 像表一样查询
SELECT * FROM user_emails WHERE name LIKE 'J%';
-- 使用WHERE条件
SELECT * FROM user_order_summary WHERE total_amount > 1000;
-- 使用ORDER BY和LIMIT
SELECT * FROM user_order_summary ORDER BY total_amount DESC LIMIT 5;
-- 使用聚合函数
SELECT AVG(total_amount) FROM user_order_summary;
4.2 连接视图 #
sql
-- 视图与其他表连接
SELECT
uos.name,
uos.total_amount,
d.name AS department
FROM user_order_summary uos
LEFT JOIN departments d ON uos.department_id = d.id;
-- 视图与视图连接
SELECT
u1.name,
u2.order_count
FROM user_emails u1
JOIN user_order_summary u2 ON u1.id = u2.id;
4.3 嵌套视图 #
sql
-- 基于视图创建视图
CREATE VIEW high_value_customers AS
SELECT * FROM user_order_summary WHERE total_amount > 1000;
-- 使用嵌套视图
SELECT * FROM high_value_customers WHERE order_count > 5;
五、可更新视图 #
5.1 可更新视图条件 #
text
可更新视图条件
├── 不包含聚合函数
│ └── SUM, COUNT, AVG, MAX, MIN等
├── 不包含DISTINCT
├── 不包含GROUP BY
├── 不包含HAVING
├── 不包含UNION
├── 不包含子查询(某些情况)
└── 只引用一个表(某些情况)
5.2 通过视图插入数据 #
sql
-- 创建简单视图
CREATE VIEW user_basic AS
SELECT id, name, email FROM users;
-- 通过视图插入
INSERT INTO user_basic (name, email) VALUES ('NewUser', 'new@example.com');
-- 验证
SELECT * FROM users WHERE name = 'NewUser';
5.3 通过视图更新数据 #
sql
-- 通过视图更新
UPDATE user_basic SET email = 'updated@example.com' WHERE id = 1;
-- 验证
SELECT * FROM users WHERE id = 1;
5.4 通过视图删除数据 #
sql
-- 通过视图删除
DELETE FROM user_basic WHERE id = 1;
-- 验证
SELECT * FROM users WHERE id = 1;
5.5 多表视图更新 #
sql
-- MariaDB支持多表视图更新(有条件)
CREATE VIEW user_department AS
SELECT u.id, u.name, u.department_id, d.name AS department_name
FROM users u
LEFT JOIN departments d ON u.department_id = d.id;
-- 可以更新users表的列
UPDATE user_department SET name = 'Updated' WHERE id = 1;
-- 不能更新departments表的列(需要触发器或存储过程)
六、修改视图 #
6.1 使用CREATE OR REPLACE #
sql
-- 替换视图定义
CREATE OR REPLACE VIEW user_emails AS
SELECT id, name, email, status, created_at FROM users;
6.2 使用ALTER VIEW #
sql
-- 修改视图
ALTER VIEW user_emails AS
SELECT id, name, email FROM users WHERE status = 1;
七、删除视图 #
7.1 DROP VIEW #
sql
-- 删除视图
DROP VIEW user_emails;
-- 如果存在则删除
DROP VIEW IF EXISTS user_emails;
-- 删除多个视图
DROP VIEW view1, view2, view3;
八、视图应用场景 #
8.1 简化复杂查询 #
sql
-- 复杂报表查询
CREATE VIEW monthly_sales_report AS
SELECT
DATE_FORMAT(order_date, '%Y-%m') AS month,
COUNT(*) AS order_count,
SUM(amount) AS total_sales,
AVG(amount) AS avg_order_value
FROM orders
GROUP BY DATE_FORMAT(order_date, '%Y-%m')
ORDER BY month DESC;
-- 使用视图
SELECT * FROM monthly_sales_report WHERE month = '2024-01';
8.2 数据安全 #
sql
-- 只暴露部分列
CREATE VIEW user_public_info AS
SELECT id, name FROM users;
-- 只暴露部分行
CREATE VIEW active_orders AS
SELECT * FROM orders WHERE status = 'active';
-- 授予视图权限
GRANT SELECT ON mydb.user_public_info TO 'readonly'@'localhost';
8.3 数据转换 #
sql
-- 格式化数据
CREATE VIEW user_display AS
SELECT
id,
name,
UPPER(name) AS name_upper,
LOWER(email) AS email_lower,
DATE_FORMAT(created_at, '%Y-%m-%d') AS created_date,
CASE status
WHEN 1 THEN 'Active'
ELSE 'Inactive'
END AS status_text
FROM users;
8.4 兼容旧接口 #
sql
-- 表结构变化后,通过视图保持兼容
-- 原表: users (id, name, email)
-- 新表: users (id, first_name, last_name, email)
CREATE VIEW users_compat AS
SELECT
id,
CONCAT(first_name, ' ', last_name) AS name,
email
FROM users;
九、视图性能 #
9.1 视图执行 #
sql
-- 视图不存储数据,每次查询都执行定义
-- 简单视图:性能影响小
-- 复杂视图:可能有性能问题
-- 查看执行计划
EXPLAIN SELECT * FROM user_order_summary WHERE id = 1;
9.2 视图优化 #
sql
-- 1. 使用索引
-- 基表的索引会自动用于视图查询
-- 2. 避免复杂嵌套
-- 减少视图嵌套层数
-- 3. 使用物化视图(MariaDB不支持原生物化视图)
-- 可以使用表替代
-- 4. 考虑使用存储过程替代复杂视图
9.3 视图vs表 #
| 特性 | 视图 | 表 |
|---|---|---|
| 存储空间 | 只存定义 | 存储数据 |
| 更新性能 | 无需维护 | 需要维护 |
| 查询性能 | 每次执行查询 | 直接读取 |
| 数据实时性 | 实时 | 实时 |
十、高级视图特性 #
10.1 使用变量 #
sql
-- 视图中可以使用用户变量
SET @min_amount = 1000;
CREATE VIEW high_value_orders AS
SELECT * FROM orders WHERE amount > @min_amount;
-- 注意:变量值在创建时确定
10.2 使用函数 #
sql
-- 视图中使用函数
CREATE VIEW recent_orders AS
SELECT * FROM orders
WHERE order_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY);
10.3 算法选择 #
sql
-- MERGE:合并视图定义到查询
CREATE ALGORITHM = MERGE VIEW user_emails AS
SELECT id, name, email FROM users;
-- TEMPTABLE:创建临时表
CREATE ALGORITHM = TEMPTABLE VIEW user_summary AS
SELECT user_id, COUNT(*) AS count FROM orders GROUP BY user_id;
-- UNDEFINED:由优化器选择(默认)
CREATE ALGORITHM = UNDEFINED VIEW user_info AS
SELECT id, name FROM users;
十一、最佳实践 #
11.1 视图命名规范 #
sql
-- 推荐命名
CREATE VIEW v_user_emails AS ...; -- 前缀v_
CREATE VIEW view_user_emails AS ...; -- 前缀view_
CREATE VIEW user_emails_view AS ...; -- 后缀_view
-- 描述性命名
CREATE VIEW active_user_orders AS ...;
CREATE VIEW monthly_sales_summary AS ...;
11.2 视图使用建议 #
| 建议 | 说明 |
|---|---|
| 简单视图 | 避免过于复杂的查询 |
| 适当嵌套 | 避免过多层嵌套 |
| 安全控制 | 使用视图限制数据访问 |
| 性能考虑 | 复杂视图考虑替代方案 |
| 文档注释 | 为视图添加注释 |
十二、总结 #
视图要点:
| 操作 | 语法 |
|---|---|
| 创建 | CREATE VIEW … AS SELECT … |
| 查看 | SHOW CREATE VIEW |
| 修改 | ALTER VIEW / CREATE OR REPLACE VIEW |
| 删除 | DROP VIEW |
| 查询 | SELECT … FROM view_name |
最佳实践:
- 使用视图简化复杂查询
- 使用视图实现数据安全
- 避免过度嵌套视图
- 注意视图性能影响
- 保持视图定义简洁
下一步,让我们学习存储过程!
最后更新:2026-03-27