學 SQL 的時候,你可能會有一個疑惑:
為什麼我寫的順序是 SELECT → FROM → WHERE,但有些語法卻好像不是按照這個順序執行?
這是因為 SQL 的「撰寫順序」和「執行順序」是不一樣的。
這篇文章會帶你了解資料庫真正的執行順序,讓你知道為什麼有些寫法可以,有些不行。
SQL 的撰寫順序與執行順序
先看一個簡單的 SELECT 指令:
SELECT id, CONCAT(姓, 名) AS 全名
FROM 會員
WHERE 姓 = '王'按照撰寫順序,這個指令做了三件事:
SELECT id, CONCAT(姓, 名) AS 全名:挑出要呈現的欄位FROM 會員:指定從哪張表單拿資料WHERE 姓 = '王':篩選出姓王的人
問題來了:資料庫是按照你寫的順序執行嗎?
不是。
從手工整理資料理解執行順序
假設你今天不用資料庫,要用純手工來整理這些資料,你會怎麼做?
你一定會先知道「資料從哪來」,也就是先執行 FROM,把會員表單的資料拿出來。
拿到資料之後,你會先做「篩選」,也就是執行 WHERE,把不符合條件的資料先濾掉。這樣可以減少資料量,後面處理起來比較快。
最後才做「輸出」,也就是執行 SELECT,從篩選後的資料中挑出你要的欄位、做計算、產出結果。
資料庫的邏輯也是一樣的。
SELECT 指令的真正執行順序
資料庫執行 SELECT 指令的順序是這樣的:
| 順序 | 子句 | 做的事情 |
|---|---|---|
| 1 | FROM | 先決定從哪張表單拿資料(輸入) |
| 2 | WHERE | 篩選出符合條件的資料(轉換) |
| 3 | SELECT | 挑出要呈現的欄位、做計算(輸出) |
用前面的例子來說:
第一步:FROM 會員
先從「會員」這張表單把所有資料拿出來。
第二步:WHERE 姓 = ‘王’
從這些資料中,篩選出姓是「王」的那幾筆。
為什麼要先篩選?
因為這樣比較節省效能。
如果先把全部資料都算完,最後才篩選,那不是很浪費嗎?
第三步:SELECT id, CONCAT(姓, 名) AS 全名
最後,從篩選後的資料中:
- 把
id直接輸出 - 把
姓和名用CONCAT連接起來,取別名叫全名
這樣就產出一張臨時的表單,有兩個欄位:id 和 全名。
為什麼別名不能在 WHERE 裡面用?
了解執行順序之後,你就能回答這個常見問題。
看這個例子:
SELECT id, CONCAT(姓, 名) AS 全名
FROM 會員
WHERE 全名 = '王大明' -- 這樣寫會報錯!為什麼不能在 WHERE 裡面用 全名 這個別名?
回顧一下執行順序:
- FROM(先執行)
- WHERE(第二個執行)
- SELECT(最後執行)
全名 這個別名是在 SELECT 階段才定義的。
但 WHERE 在 SELECT 之前就執行了。
所以在 WHERE 執行的時候,資料庫根本還不知道 全名 是什麼。
這就是為什麼會報錯。
了解執行計畫的好處
不管你換什麼表單、換什麼欄位、換什麼篩選條件,執行順序都不會改變:
FROM → WHERE → SELECT
這個順序就是資料庫的「執行計畫(Execution Plan)」,它是固定的邏輯,不會因為你的資料不同而改變。
了解執行計畫有幾個好處:
- 語法不用死背:你可以用邏輯推論出什麼寫法可以、什麼不行
- 除錯更容易:報錯的時候,你會知道是哪個階段出了問題
- 基礎更扎實:你會真正理解 SQL 的設計邏輯,而不是只會照抄範例
之後學到更多子句(像是 GROUP BY、HAVING、ORDER BY)的時候,我也會帶你看它們在執行計畫中的位置。
搞清楚這件事,學 SQL 會輕鬆很多。
小結
這篇文章介紹了 SQL SELECT 的執行順序:
- FROM 最先執行:先決定輸入的資料來源
- WHERE 第二個執行:篩選出符合條件的資料
- SELECT 最後執行:挑出欄位、做計算、產出結果
理解這個順序之後,你就能解釋為什麼 SELECT 的別名不能在 WHERE 裡面用。
記住:不要死背語法,要理解背後的執行邏輯。