CodeGym /课程 /SQL SELF /PostgreSQL 里的视图(`VIEW`)

PostgreSQL 里的视图(`VIEW`)

SQL SELF
第 13 级, 课程 4
可用

有时候 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
  1. 视图:课程数量

这个视图统计每个学生选了多少门课:

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
  1. 视图:平均分 这个是学生的平均分(没分数就是 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;
  1. 怎么用这些 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 特别有用的时候

  1. 做报表

一个 VIEW 就是一套逻辑。你可以搞个 report_enrollments_by_month、report_payments_by_year 之类的。

  1. 权限控制

建个 VIEW,只显示有限的数据(比如不带个人信息),然后只给别人查这个视图的权限。

  1. 复用查询

不用再 copy 子查询了——直接给它起个 VIEW 名字。

建议

  • 名字要起得明白点: view_avg_scores_by_group、active_users_view —— 这样一看就懂。
  • 别搞一堆 VIEW 套 VIEW 再套 VIEW —— 这样会让人看不懂,也难调试。
  • 注意性能: PostgreSQL 每次查 VIEW 都会重新算,除非你用 MATERIALIZED VIEW。

VIEW 是 PostgreSQL 里最简单又好用的工具之一。你不用学新东西,只要换个思路:“要不把这个查询存起来当表用?” 如果你的查询写得很臃肿——那它八成就该变成 VIEW 了。

2
任务
SQL SELF, 第 13 级, 课程 4
已锁定
创建一个简单的视图
创建一个简单的视图
2
任务
SQL SELF, 第 13 级, 课程 4
已锁定
从多张表合并数据的视图
从多张表合并数据的视图
1
调查/小测验
嵌套SELECT第 13 级,课程 4
不可用
嵌套SELECT
嵌套SELECT
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION