SQLite视图 #
一、视图概述 #
1.1 什么是视图 #
sql
-- 视图是存储的查询,表现为虚拟表
-- 视图不存储数据,每次查询时动态生成
-- 视图的特点:
-- 1. 简化复杂查询
-- 2. 提供数据抽象层
-- 3. 实现数据安全
-- 4. 不占用存储空间(只存储定义)
1.2 视图类型 #
text
SQLite 视图类型:
├── 普通视图
├── 临时视图(TEMP VIEW)
└── 可更新视图(有限支持)
二、创建视图 #
2.1 基本语法 #
sql
-- CREATE VIEW 基本语法
CREATE VIEW view_name AS
SELECT statement;
-- 示例表
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
email TEXT,
department_id INTEGER,
salary REAL
);
CREATE TABLE departments (
id INTEGER PRIMARY KEY,
name TEXT
);
-- 创建简单视图
CREATE VIEW user_emails AS
SELECT name, email FROM users;
-- 使用视图
SELECT * FROM user_emails;
2.2 复杂视图 #
sql
-- 创建带JOIN的视图
CREATE VIEW user_departments AS
SELECT
u.name AS user_name,
u.email,
d.name AS department_name
FROM users u
LEFT JOIN departments d ON u.department_id = d.id;
-- 创建带聚合的视图
CREATE VIEW department_stats AS
SELECT
d.name AS department_name,
COUNT(u.id) AS employee_count,
AVG(u.salary) AS avg_salary,
MAX(u.salary) AS max_salary,
MIN(u.salary) AS min_salary
FROM departments d
LEFT JOIN users u ON d.id = u.department_id
GROUP BY d.id;
2.3 临时视图 #
sql
-- 临时视图只在当前连接存在
CREATE TEMP VIEW temp_results AS
SELECT * FROM users WHERE status = 1;
-- 或
CREATE TEMPORARY VIEW temp_results AS
SELECT * FROM users WHERE status = 1;
-- 连接关闭后自动删除
2.4 IF NOT EXISTS #
sql
-- 避免重复创建
CREATE VIEW IF NOT EXISTS user_emails AS
SELECT name, email FROM users;
三、使用视图 #
3.1 查询视图 #
sql
-- 像表一样查询视图
SELECT * FROM user_emails;
SELECT * FROM user_departments WHERE department_name = 'Engineering';
-- 在视图中使用WHERE
SELECT user_name, email
FROM user_departments
WHERE department_name = 'Engineering';
-- 在视图中使用ORDER BY
SELECT * FROM department_stats ORDER BY employee_count DESC;
3.2 视图嵌套 #
sql
-- 在另一个视图中使用视图
CREATE VIEW high_salary_employees AS
SELECT user_name, salary
FROM user_departments ud
JOIN users u ON ud.email = u.email
WHERE u.salary > 100000;
-- 或直接基于视图创建
CREATE VIEW engineering_employees AS
SELECT * FROM user_departments WHERE department_name = 'Engineering';
3.3 在JOIN中使用视图 #
sql
-- 视图可以参与JOIN
SELECT
ds.department_name,
ds.employee_count,
e.project_count
FROM department_stats ds
LEFT JOIN (
SELECT department_id, COUNT(*) AS project_count
FROM projects
GROUP BY department_id
) e ON ds.department_id = e.department_id;
四、修改视图 #
4.1 删除并重建 #
sql
-- SQLite 不支持 ALTER VIEW
-- 需要删除并重建
DROP VIEW IF EXISTS user_emails;
CREATE VIEW user_emails AS
SELECT name, email, department_id FROM users;
五、删除视图 #
5.1 DROP VIEW #
sql
-- 删除视图
DROP VIEW user_emails;
-- 使用 IF EXISTS
DROP VIEW IF EXISTS user_emails;
六、可更新视图 #
6.1 可更新视图条件 #
sql
-- SQLite 对可更新视图有限支持
-- 条件:
-- 1. 视图基于单个表
-- 2. 没有 DISTINCT、GROUP BY、HAVING
-- 3. 没有聚合函数
-- 4. 没有 UNION、EXCEPT、INTERSECT
-- 5. 没有子查询
-- 可更新视图示例
CREATE VIEW active_users AS
SELECT id, name, email FROM users WHERE status = 1;
-- 通过视图插入
INSERT INTO active_users (name, email) VALUES ('Test', 'test@example.com');
-- 通过视图更新
UPDATE active_users SET name = 'Updated' WHERE id = 1;
-- 通过视图删除
DELETE FROM active_users WHERE id = 1;
6.2 使用INSTEAD OF触发器 #
sql
-- 对于复杂视图,使用INSTEAD OF触发器实现更新
-- 创建复杂视图
CREATE VIEW user_department_view AS
SELECT
u.id,
u.name,
u.email,
d.name AS department_name
FROM users u
LEFT JOIN departments d ON u.department_id = d.id;
-- 创建INSERT触发器
CREATE TRIGGER trg_user_dept_insert
INSTEAD OF INSERT ON user_department_view
BEGIN
INSERT OR IGNORE INTO departments (name) VALUES (NEW.department_name);
INSERT INTO users (name, email, department_id)
VALUES (
NEW.name,
NEW.email,
(SELECT id FROM departments WHERE name = NEW.department_name)
);
END;
-- 创建UPDATE触发器
CREATE TRIGGER trg_user_dept_update
INSTEAD OF UPDATE ON user_department_view
BEGIN
UPDATE users
SET name = NEW.name, email = NEW.email
WHERE id = OLD.id;
UPDATE departments
SET name = NEW.department_name
WHERE id = (SELECT department_id FROM users WHERE id = OLD.id);
END;
-- 创建DELETE触发器
CREATE TRIGGER trg_user_dept_delete
INSTEAD OF DELETE ON user_department_view
BEGIN
DELETE FROM users WHERE id = OLD.id;
END;
七、查看视图 #
7.1 查看视图定义 #
sql
-- 查看视图SQL
SELECT name, sql FROM sqlite_master WHERE type = 'view';
-- 查看特定视图
SELECT sql FROM sqlite_master WHERE type = 'view' AND name = 'user_emails';
-- 使用命令行
.schema user_emails
7.2 查看所有视图 #
sql
-- 列出所有视图
SELECT name FROM sqlite_master WHERE type = 'view';
-- 列出所有表和视图
SELECT name, type FROM sqlite_master WHERE type IN ('table', 'view');
八、视图应用场景 #
8.1 简化复杂查询 #
sql
-- 复杂查询封装为视图
CREATE VIEW order_summary AS
SELECT
o.id AS order_id,
u.name AS customer_name,
o.order_date,
COUNT(oi.id) AS item_count,
SUM(oi.quantity * oi.price) AS total_amount
FROM orders o
JOIN users u ON o.user_id = u.id
JOIN order_items oi ON o.id = oi.order_id
GROUP BY o.id;
-- 使用简化后的视图
SELECT * FROM order_summary WHERE total_amount > 1000;
8.2 数据安全 #
sql
-- 限制敏感数据访问
CREATE VIEW public_users AS
SELECT id, name FROM users; -- 不暴露email和salary
-- 应用程序使用视图而不是基表
SELECT * FROM public_users;
8.3 数据抽象 #
sql
-- 隐藏表结构变化
CREATE VIEW customer_info AS
SELECT
id,
first_name || ' ' || last_name AS full_name,
email
FROM customers;
-- 即使customers表结构变化,视图可以保持不变
8.4 报表视图 #
sql
-- 创建报表专用视图
CREATE VIEW monthly_sales_report AS
SELECT
strftime('%Y-%m', order_date) AS month,
COUNT(*) AS order_count,
SUM(total) AS total_sales,
AVG(total) AS avg_order_value
FROM orders
GROUP BY strftime('%Y-%m', order_date)
ORDER BY month;
-- 生成报表
SELECT * FROM monthly_sales_report;
九、视图性能 #
9.1 视图性能特点 #
sql
-- 视图不存储数据,每次查询都执行底层查询
-- 复杂视图可能影响性能
-- 对于频繁使用的复杂视图,考虑:
-- 1. 物化视图(使用表存储结果)
-- 2. 缓存结果
-- 3. 优化底层查询
-- 创建物化视图(使用表)
CREATE TABLE mv_monthly_sales AS
SELECT
strftime('%Y-%m', order_date) AS month,
SUM(total) AS total_sales
FROM orders
GROUP BY strftime('%Y-%m', order_date);
-- 定期更新
DELETE FROM mv_monthly_sales;
INSERT INTO mv_monthly_sales
SELECT strftime('%Y-%m', order_date), SUM(total)
FROM orders GROUP BY strftime('%Y-%m', order_date);
9.2 使用EXPLAIN分析 #
sql
-- 分析视图查询计划
EXPLAIN QUERY PLAN SELECT * FROM user_departments;
-- 检查是否使用了索引
十、总结 #
视图操作 #
| 操作 | 语法 |
|---|---|
| 创建视图 | CREATE VIEW name AS SELECT … |
| 创建临时视图 | CREATE TEMP VIEW name AS SELECT … |
| 删除视图 | DROP VIEW name |
| 查看视图 | SELECT * FROM sqlite_master WHERE type=‘view’ |
最佳实践 #
- 使用视图简化复杂查询
- 使用视图实现数据安全
- 避免过度嵌套视图
- 复杂视图考虑使用物化表
- 使用INSTEAD OF触发器实现可更新视图
下一步,让我们学习触发器!
最后更新:2026-03-27