有时候 SQL 查询写着写着就变得又长又复杂,还经常重复。比如你要做个学生的报告,统计他们的平均分和课程数量——结果同一个子查询写了五遍。为了不一直 copy paste,直接用 视图 —— 也就是 VIEW。
VIEW 就像是“保存的查询”,你可以给它起个名字,然后像表一样用它。 它不存数据,只存查询结构。
这个功能特别适合:
- 让 SQL 代码更好读;
- 复用复杂的查询逻辑;
- 把技术细节藏起来,不让用户看到;
- 做权限控制(只给看需要的数据)。
VIEW 怎么工作?
创建视图就是基于 SELECT 查询造一个伪表。比如:
CREATE VIEW student_avg_grades AS
SELECT
s.student_id,
s.name,
AVG(g.grade) AS avg_grade
FROM
students s
JOIN
grades g ON s.student_id = g.student_id
GROUP BY
s.student_id, s.name;
现在你可以像查普通表一样查 student_avg_grades:
SELECT * FROM student_avg_grades WHERE avg_grade > 4.5;
大学里的例子
你经常分析学生、课程和成绩。假设你要做个每个学生的汇总报告:
- 名字,
- 选了多少门课,
- 平均分。
如果一口气全写进一个 SQL,会又臭又长还难读。更好的做法是拆开:先建两个视图(VIEW),再把它们合起来用。
students 表
| id | name |
|---|---|
| 1 | Alex Lin |
| 2 | Anna Song |
| 3 | Maria Chi |
| 4 | Dan Seth |
enrollments 表
| student_id | course_id | grade |
|---|---|---|
| 1 | 1 | 90 |
| 1 | 2 | 85 |
| 2 | 2 | 88 |
| 2 | 3 | 91 |
| 3 | 1 | 75 |
| 3 | 3 | NULL |
- 视图:课程数量
这个视图统计每个学生选了多少门课:
CREATE VIEW student_course_count AS
SELECT
student_id,
COUNT(*) AS course_count
FROM
enrollments
GROUP BY student_id;
结果:
| name |
|---|
| Alex Lin |
| Anna Song |
| Maria Chi |
- 视图:平均分 这个是学生的平均分(没分数就是 NULL,不算进去):
CREATE VIEW student_avg_grade AS
SELECT
student_id,
AVG(grade) AS avg_grade
FROM
enrollments
WHERE grade IS NOT NULL
GROUP BY student_id;
- 怎么用这些
VIEW
SELECT
s.name,
c.course_count,
a.avg_grade
FROM
students s
LEFT JOIN student_course_count c ON s.student_id = c.student_id
LEFT JOIN student_avg_grade a ON s.student_id = a.student_id;
现在你的查询又干净又好懂。最重要的是——维护起来超简单。
VIEW 的可更新性
视图一般 不存数据 —— 就是个查询“壳”。不过,有时候你也能用它们来 更新 数据,只要 VIEW 满足一些条件(比如不能有 JOIN、GROUP BY、聚合函数和子查询)。
可更新视图的例子:
CREATE VIEW active_students AS
SELECT * FROM students WHERE active = true;
现在你可以这样操作:
UPDATE active_students SET name = '伊万·彼得罗夫' WHERE student_id = 2;
但如果 VIEW 很复杂(比如有 JOIN 或 GROUP BY),那它就 只能读 不能写。要更新的话可以用 INSTEAD OF 触发器,不过这个就有点进阶了。
怎么删或改 VIEW
删除:
DROP VIEW student_avg_grade;
更新:
CREATE OR REPLACE VIEW student_avg_grade AS
SELECT student_id, ROUND(AVG(grade), 2) AS avg_grade
FROM grades
GROUP BY student_id;
举例:VIEW 特别有用的时候
- 做报表
一个 VIEW 就是一套逻辑。你可以搞个 report_enrollments_by_month、report_payments_by_year 之类的。
- 权限控制
建个 VIEW,只显示有限的数据(比如不带个人信息),然后只给别人查这个视图的权限。
- 复用查询
不用再 copy 子查询了——直接给它起个 VIEW 名字。
建议
- 名字要起得明白点:
view_avg_scores_by_group、active_users_view—— 这样一看就懂。 - 别搞一堆
VIEW套VIEW再套VIEW—— 这样会让人看不懂,也难调试。 - 注意性能: PostgreSQL 每次查
VIEW都会重新算,除非你用MATERIALIZED VIEW。
VIEW 是 PostgreSQL 里最简单又好用的工具之一。你不用学新东西,只要换个思路:“要不把这个查询存起来当表用?” 如果你的查询写得很臃肿——那它八成就该变成 VIEW 了。
GO TO FULL VERSION