首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle ROWNUM 偽欄位完整解析:為何 >、>=、=、BETWEEN 查不到資料與正確分頁寫法

     編輯:Oracle 資料庫基礎

ROWNUM 是 Oracle 查詢結果集產生之後依序分配的偽欄位,永遠從 1 開始遞增。這特性導致 ROWNUM > 10、ROWNUM = 5、ROWNUM BETWEEN 2 AND 10 永遠回傳零筆。本文透過 4 個經典現象解析原理,並給出標準分頁與區間查詢寫法。

核心機制:先有結果集,再產生 ROWNUM

SELECT ROWNUM, c1 FROM t1 WHERE ROWNUM < 10;  -- 正常:前 9 筆
SELECT ROWNUM, c1 FROM t1 WHERE ROWNUM > 10;  -- 永遠 0 筆!

執行邏輯:

  1. 從資料檔/緩衝區讀取第 1 筆符合條件的列 → 分配 ROWNUM=1。
  2. 檢查 WHERE ROWNUM > 10 → 1 > 10 為假 → 捨棄。
  3. 讀取第 2 筆 → 分配 ROWNUM=1(因前一筆被捨棄) → 同樣被捨棄。
  4. 循環至結束,永無機會產生 ROWNUM > 1。

四大經典現象解析

查詢結果原因
ROWNUM != 10前 9 筆第 10 筆產生 ROWNUM=10 被排除,第 11 筆變 ROWNUM=10 又被排除,以此類推
ROWNUM > 10 筆第一筆即為 1,不符合 >1 被捨棄,後續永遠是 1
ROWNUM >= 1 / ROWNUM > 0全部條件永真,不濾除任何列
ROWNUM BETWEEN 2 AND 100 筆同理,永無機會產生 ROWNUM=2

正確寫法:子查詢先產生 ROWNUM,外層再篩選

分頁查詢(第 11-20 筆)

SELECT *
FROM (
  SELECT ROWNUM AS rn, t.*
  FROM   (SELECT * FROM t1 ORDER BY c1) t
  WHERE  ROWNUM <= 20
)
WHERE rn > 10;

關鍵點:

  1. 最內層 ORDER BY 確保排序確定性。
  2. 中層 WHERE ROWNUM <= 20 截取前 20 筆(利用 ROWNUM < 條件特性)。
  3. 外層 WHERE rn > 10 過濾出第 11-20 筆(rn 為真實欄位,可任意比較)。

12c+ 簡潔語法:OFFSET ... FETCH

SELECT * FROM t1 ORDER BY c1
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

ROWNUM vs ROWID

特性ROWNUMROWID
本質查詢結果集序號(邏輯)資料列物理位址(檔案號+區塊號+槽號)
穩定性查詢每次重新產生列未移動(非遷移、非分區移動)時永久不變
用途分頁、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 查詢。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved