CodeGym /課程 /SQL SELF /PostgreSQL 裡的視圖 (`VIEW`)

PostgreSQL 裡的視圖 (`VIEW`)

SQL SELF
等級 13, 課堂 4
開放

有時候 SQL 查詢會變得超大、超複雜還一直重複。例如你要做一個學生的成績平均跟修課數的報表——結果同一個子查詢你寫了五次。這種時候就別再複製貼上啦,直接用 視圖——也就是 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. 重複用

不用再複製子查詢——直接給它一個 VIEW 名字。

建議

  • 名字要清楚: view_avg_scores_by_group、active_users_view 這樣一看就懂。
  • 不要一直巢狀 VIEW 裡面包 VIEW 再包 VIEW——這樣超難懂也難 debug。
  • 注意效能: 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