子查詢 允許將一個 SELECT 的結果作為另一個查詢的輸入值,可出現在 WHERE、FROM、SELECT 列表中。本文聚焦 WHERE 子句中的標量與多值子查詢,並解決「單值預期卻返回多值」的經典運行時錯誤。
-- 找出與 Brazil 同區域的所有國家
SELECT name FROM bbc
WHERE region = (SELECT region FROM bbc WHERE name = 'Brazil');
外層查詢預期子查詢返回**單一標量值** (此處為 'Americas')。
若表中存在兩筆 name='Brazil' 但 region 不同 (如 'Americas', 'Europe'),子查詢返回兩值。外層 WHERE region = ('Americas', 'Europe') 為**非法語法**,拋出運行時錯誤 (非編譯錯誤)。
-- 安全寫法:無論 Brazil 有幾筆記錄皆不報錯
SELECT name FROM bbc
WHERE region IN (SELECT region FROM bbc WHERE name = 'Brazil');
IN 接受列表值,完美解決「單值 vs 多值」不確定性問題。**最佳實踐:除非業務邏輯絕對保證單行,否則優先使用 IN 而非 =。**
SELECT name FROM bbc
WHERE population > (SELECT population FROM bbc WHERE name = 'Russia');
SELECT * FROM bbc
WHERE region IN (SELECT region FROM bbc WHERE name IN ('India', 'Iran'));
SELECT name FROM bbc
WHERE region = 'Europe'
AND gdp/population > (SELECT gdp/population FROM bbc WHERE name = 'United Kingdom');
| 位置 | 名稱 | 回傳要求 | 範例 |
|---|---|---|---|
WHERE | 巢狀子查詢 | 標量 (單值) 或列表 (配合 IN/EXISTS/ANY/ALL) | WHERE col > (SELECT ...) |
FROM | 衍生表 / 內聯檢視 | 資料表結果集 (需別名) | FROM (SELECT ... ) AS t |
SELECT 列表 | 標量子查詢 | 單一值 (單行單列) | SELECT col, (SELECT ...) AS extra |
WHERE) 可能逐行執行,大數據量下優先改寫為 JOIN 或 APPLY。EXISTS / NOT EXISTS 通常優於 IN / NOT IN (尤其含 NULL 時)。