ROWNUM 是 Oracle 最常被誤解的偽欄位。它不是「資料列的固有編號」,而是「查詢結果集產生順序的流水號」。本文深入解析其運作機制、常見陷阱 (如 ROWNUM > 10 無資料)、正確分頁寫法、排序時機差異,以及效能優化價值。
執行順序 (關鍵!):
FROM / WHERE 子句執行,產生符合條件的原始列集。SELECT 列表運算 (含函數、運算式)。GROUP BY / HAVING。ORDER BY 排序 (最後才發生)。→ ROWNUM 指派發生在 ORDER BY 之前,這是所有誤解的根源。
ROWNUM > 10 永無資料?SELECT * FROM tbrole WHERE ROWNUM > 10;
邏輯推演:
> 10 → 捨棄。結論:ROWNUM 只能用於 <、<=、!= (或 BETWEEN 1 AND n),不能直接用 >、>=、= (大於 1)、BETWEEN m AND n (m>1)。
-- 取第 11-20 筆 (每頁 10 筆)
SELECT *
FROM (
SELECT r.*, ROWNUM rn
FROM (
SELECT * FROM tbrole ORDER BY create_time ASC
) r
WHERE ROWNUM <= 20
)
WHERE rn >= 11;
三層結構解析:
ORDER BY 先排序,產生有序結果集。ROWNUM <= 20 截取前 20 筆,同時賦予 rn 序號。rn >= 11 篩選目標頁面區間。錯誤寫法:將 ORDER BY 放在最外層 — 排序發生在 ROWNUM 指派之後,分頁結果錯亂。
SELECT * FROM tbrole
ORDER BY create_time ASC
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
標準 SQL:2008 語法,Oracle 12c 完整支援,執行計畫自動優化,強烈建議新專案採用。
WHERE ROWNUM <= n 讓優化器採用 COUNT STOPKEY 操作,一旦湊齊 n 筆即停止掃描與排序,大幅減少 TEMP 表空間使用與 CPU 消耗。FIRST_ROWS(n) Hint 可進一步引導優化器選擇巢狀迴圈、索引存取等優首筆回應的計畫。| 特性 | ROWNUM | ROWID |
|---|---|---|
| 性質 | 查詢結果集流水號 (邏輯) | 資料列物理位址 (絕對) |
| 穩定性 | 每次查詢重新指派 | 列不移動則永久不變 |
| 用途 | 分頁、Top-N、限制筆數 | 精確定位/刪除重複列、直接存取 |
WHERE ROWNUM <= 10 / ROWNUM < 10 / ROWNUM BETWEEN 1 AND 10WHERE ROWNUM > 10 / ROWNUM = 5 / ROWNUM BETWEEN 11 AND 20 (直接用)OFFSET ... FETCHROWNUM <= n 可觸發 STOPKEY 優化,減少排序 I/O