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

Oracle ROWNUM 與 ROWID 深度解析:偽欄位特性、分頁查詢陷阱與最佳實踐

     編輯:Oracle 資料庫基礎

ROWNUM 與 ROWID 是 Oracle 兩大核心偽欄位,前者用於結果集排序標記,後者為物理地址唯一標識。本文深度剖析 ROWNUM 遞增邏輯導致的 =n / >n 查詢失效原理、分頁查詢正確寫法、ROWID 物理定位特性與實務應用場景。

一、 ROWNUM 本質與遞增邏輯

  • 定義:查詢結果集產生時動態分配,**不儲存於資料表**
  • 遞增規則:從 1 開始,僅當列符合 WHERE 條件且被加入結果集時才遞增
  • 關鍵推論:必須存在 ROWNUM=1,才可能產生 ROWNUM=2

二、 常見查詢陷阱與原理

三、 分頁查詢正確寫法

錯誤嘗試

-- 第 11~20 列
SELECT * FROM t WHERE rownum BETWEEN 11 AND 20;  -- 永遠空結果

標準解法:內層賦予 ROWNUM 別名,外層篩選

SELECT * FROM (
  SELECT t.*, ROWNUM rn
  FROM   (SELECT * FROM large_table WHERE status='A' ORDER BY created_dt DESC) t
  WHERE  ROWNUM <= 20
)
WHERE rn >= 11;

關鍵點:

  1. 最內層完成業務過濾 + 排序
  2. 中層賦予 ROWNUM rn 並截取上限 (WHERE ROWNUM <= :end)
  3. 最外層篩選下限 (WHERE rn >= :start)

12c+ 簡潔語法 (OFFSET/FETCH)

SELECT * FROM large_table
WHERE status = 'A'
ORDER BY created_dt DESC
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

舊版替代方案:MINUS 集合運算 (效能較差)

SELECT * FROM t WHERE status='A' AND rownum <= 20
MINUS
SELECT * FROM t WHERE status='A' AND rownum <= 10;

四、 ROWNUM 停止掃描特性 (短路優化)

SELECT * FROM huge_table WHERE rownum <= 100;

Oracle **不會** Full Scan 整張表。一旦收集滿 100 列,**立即停止掃描** 回傳結果。此特性可用於:

  • 大表隨機抽樣:WHERE rownum <= 1000
  • 存在性檢查:SELECT 1 FROM t WHERE cond AND rownum = 1
  • Top-N 查詢配合排序 (需內層排序)

五、 ROWID:物理地址唯一標識

結構組成 (10 位元組擴展 ROWID)

查詢條件結果原因
WHERE rownum = 1✅ 回傳第一列首列產生 ROWNUM=1,符合條件
WHERE rownum <= 10✅ 回傳前 10 列依次產生 1~10,皆符合
WHERE rownum = 5❌ 空結果集首列 ROWNUM=1 ≠ 5,被過濾,無後續列產生
WHERE rownum > 5❌ 空結果集首列 ROWNUM=1 ≯ 5,被過濾,遞增鏈斷裂
WHERE rownum > 0✅ 回傳所有列所有 ROWNUM ≥ 1 皆符合

核心特性

  • 唯一且固定:列插入時分配,**唯有表移動 (MOVE/匯出入/縮表) 才改變**
  • 最快定位路徑:SELECT * FROM t WHERE rowid = 'AAAP...' 直接定位區塊/槽位,**零索引、零掃描**
  • 不可攜帶:跨資料庫/匯出入後 ROWID 失效

實務應用場景

元件位數說明
Data Object Number32 bits物件編號 (非 OBJECT_ID)
Relative File Number10 bits表空間內相對檔案號
Block Number22 bits檔案內區塊號
Row Slot16 bits區塊內列槽位

六、 綜合對照表

場景用法注意
重複資料刪除DELETE FROM t WHERE rowid NOT IN (SELECT MIN(rowid) FROM t GROUP BY pk_cols);保留最早插入列
大表分批處理PL/SQL 迴圈按 ROWID 範圍分批 UPDATE/DELETE避免長交易/Undo 爆滿
應用層快速重訪前端傳回 ROWID,後續直接定位同一交易/短時間內有效
索引組織表 (IOT) 定位IOT 亦有 LOGICAL ROWID (含主鍵 + 猜測物理位置)猜測失效回退主鍵查詢

七、 避坑指南

  1. ❌ WHERE rownum = 5 / WHERE rownum > 5 → 永遠空結果
  2. ❌ 以為 ROWNUM 反映表中物理順序 → **無關**,取決於執行計畫存取路徑
  3. ❌ 將 ROWID 儲存於應用快取長期使用 → 表 MOVE/匯出入後失效
  4. ✅ 分頁查詢**必須**三層巢狀 (內層排序/過濾 → 中層 ROWNUM 截取 → 外層篩選)
  5. ✅ 12c+ 優先使用 OFFSET/FETCH 標準語法
  6. ✅ 大表分批處理優先按 ROWID 範圍或 PK 範圍

ROWNUM 是「結果集的行號」,ROWID 是「資料的身分證」。搞清兩者本質差異、掌握分頁正確模式、善用 ROWID 物理定位優勢,是 Oracle 開發者進階的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性ROWNUMROWID
類型邏輯偽欄位 (結果集序號)物理偽欄位 (儲存地址)
生命週期查詢期間動態產生列插入時固定,移動才變
唯一性單一查詢內唯一全資料庫唯一 (含物件號)
可否 WHERE 直接用受限 (=1, <=n)完全支援 (=, IN, BETWEEN)
典型用途Top-N、分頁、存在性檢查、抽樣重複刪除、分批處理、快速重訪、IOT
跨查詢持久否是 (除非表移動)