ROWNUM 是 Oracle 查詢結果集的**順序編號**,從 1 開始,**在 WHERE 過濾前賦值**,且**早於 ORDER BY 執行**。這導致直接使用 WHERE ROWNUM = N (N>1) 永遠無結果,也解釋了為什麼排序必須在子查詢中完成。
-- 正確:子查詢先賦予 ROWNUM 別名
SELECT * FROM (
SELECT ROWNUM rn, t.* FROM test_tab t
) WHERE rn = 2;
-- 錯誤:直接過濾 ROWNUM = 2 無結果
SELECT * FROM test_tab WHERE ROWNUM = 2;
SELECT * FROM test_tab WHERE ROWNUM <= 10;
SELECT * FROM (
SELECT ROWNUM rn, t.* FROM test_tab t WHERE ROWNUM <= 10
) WHERE rn >= 4;
SELECT * FROM (
SELECT ROWNUM rn, t.* FROM (
SELECT * FROM ecode_info
WHERE a = 1
ORDER BY ecode DESC
) t
) WHERE rn > 19 AND ROWNUM < 20; -- 取第 20 行
關鍵點:最內層完成過濾與排序,中層賦予 ROWNUM,外層做範圍過濾。
Oracle 12c 引入 ANSI SQL 標準分頁語法,更簡潔、優化器支持更好:
SELECT * FROM ecode_info
WHERE a = 1
ORDER BY ecode DESC
OFFSET 19 ROWS FETCH NEXT 1 ROW ONLY; -- 取第 20 行
| 錯誤寫法 | 原因 | 正確替代 |
|---|---|---|
WHERE ROWNUM > 10 | ROWNUM 從 1 開始遞增,>10 永遠不滿足第一行 | 子查詢賦予別名後過濾 |
WHERE ROWNUM = 2 | 第一行 ROWNUM=1 不滿足,第二行變為新第一行,仍為 1 | 子查詢別名法 |
| 外層 ORDER BY 後再用 ROWNUM | ROWNUM 在 ORDER BY 前生成,順序錯亂 | 內層排序,外層分頁 |
WHERE id > :last_id AND ROWNUM <= N)。掌握 ROWNUM 的生成時機與分頁模板,是編寫高效 Oracle 分頁查詢的基礎。