ROWNUM 是 Oracle 查詢結果集產生之後依序分配的偽欄位,永遠從 1 開始遞增。這特性導致 ROWNUM > 10、ROWNUM = 5、ROWNUM BETWEEN 2 AND 10 永遠回傳零筆。本文透過 4 個經典現象解析原理,並給出標準分頁與區間查詢寫法。
SELECT ROWNUM, c1 FROM t1 WHERE ROWNUM < 10; -- 正常:前 9 筆
SELECT ROWNUM, c1 FROM t1 WHERE ROWNUM > 10; -- 永遠 0 筆!
執行邏輯:
ROWNUM=1。WHERE ROWNUM > 10 → 1 > 10 為假 → 捨棄。ROWNUM=1(因前一筆被捨棄) → 同樣被捨棄。ROWNUM > 1。| 查詢 | 結果 | 原因 |
|---|---|---|
ROWNUM != 10 | 前 9 筆 | 第 10 筆產生 ROWNUM=10 被排除,第 11 筆變 ROWNUM=10 又被排除,以此類推 |
ROWNUM > 1 | 0 筆 | 第一筆即為 1,不符合 >1 被捨棄,後續永遠是 1 |
ROWNUM >= 1 / ROWNUM > 0 | 全部 | 條件永真,不濾除任何列 |
ROWNUM BETWEEN 2 AND 10 | 0 筆 | 同理,永無機會產生 ROWNUM=2 |
SELECT *
FROM (
SELECT ROWNUM AS rn, t.*
FROM (SELECT * FROM t1 ORDER BY c1) t
WHERE ROWNUM <= 20
)
WHERE rn > 10;
關鍵點:
ORDER BY 確保排序確定性。WHERE ROWNUM <= 20 截取前 20 筆(利用 ROWNUM < 條件特性)。WHERE rn > 10 過濾出第 11-20 筆(rn 為真實欄位,可任意比較)。SELECT * FROM t1 ORDER BY c1
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
| 特性 | ROWNUM | ROWID |
|---|---|---|
| 本質 | 查詢結果集序號(邏輯) | 資料列物理位址(檔案號+區塊號+槽號) |
| 穩定性 | 查詢每次重新產生 | 列未移動(非遷移、非分區移動)時永久不變 |
| 用途 | 分頁、Top-N | 最快單列存取、刪除重複列 |
| 可作為 WHERE 條件 | 僅支援 <、<=、!= | 支援所有比較運算子 |
ROWNUM 不能加表前綴:t1.ROWNUM 錯誤。ROWNUM 必須別名(如 rn),否則外層無法區分內外層 ROWNUM。ROWNUM 與 ORDER BY:SELECT * FROM t1 WHERE ROWNUM <= 10 ORDER BY c1 先取前 10 筆(隨機物理順序)再排序,非取排序後前 10 筆。必須用子查詢先排序。徹底理解「ROWNUM 是結果集產生後的流水號」這一本質,即可避開所有比較運算子陷阱,寫出正確高效的分頁與 Top-N 查詢。