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

標準 SQL 實現分頁查詢:不依賴資料庫專屬語法的通用寫法

     編輯:關於SqlServer

Web 應用常需分頁顯示大量資料。雖然各資料庫提供專屬分頁語法(SQL Server OFFSET/FETCH、MySQL LIMIT、Oracle ROWNUM),但掌握純 ANSI SQL 分頁寫法可提高程式碼可移植性,也有助於理解分頁本質。本文示範以相關子查詢計算序數的標準做法。

核心概念:序數計算

分頁本質是「取得第 N 到 M 筆依排序鍵排序的列」。標準 SQL 無內建序數函數(SQL:2003 引入 ROW_NUMBER() 但早期版本不支援),可用相關子查詢計算「比目前列排序鍵小的列數」作為序數。

基本範例:取第 11~20 筆(以 ID 排序)

SELECT *
FROM t_table t1
WHERE (SELECT COUNT(*) FROM t_table t2 WHERE t2.id < t1.id) >= 10
  AND (SELECT COUNT(*) FROM t_table t2 WHERE t2.id < t1.id) < 20
ORDER BY t1.id;
  • t2.id < t1.id 計算嚴格小於目前列 ID 的列數 → 0-based 序數。
  • >= 10 AND < 20 對應第 11~20 筆(1-based 頁碼)。
  • 必須有唯一排序鍵(PK、UNIQUE 或組合鍵),否則同鍵值列序數相同會導致遺漏或重複。

帶條件分頁:key='123' 取第 11~20 筆

SELECT *
FROM t_table t1
WHERE (SELECT COUNT(*) FROM t_table t2 WHERE t2.id < t1.id AND t2.key = '123') >= 10
  AND (SELECT COUNT(*) FROM t_table t2 WHERE t2.id < t1.id AND t2.key = '123') < 20
  AND t1.key = '123'
ORDER BY t1.id;

子查詢與外層需完全一致的篩選條件,否則序數計算會錯誤。

效能考量與優化

問題影響對策
相關子查詢逐列執行O(N²) 複雜度,資料量大極慢僅適用小資料集(< 1 萬列)或教學示範
無索引支援全表掃描排序鍵(id)與篩選鍵(key)建立複合索引
重複計算兩個子查詢邏輯相同使用 CTE/子查詢預先計算序數

現代化改寫:CTE + ROW_NUMBER()(SQL Server 2005+, Oracle 10g+, PostgreSQL, MySQL 8.0+)

WITH Numbered AS (
    SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS rn
    FROM t_table
    WHERE key = '123'
)
SELECT * FROM Numbered WHERE rn BETWEEN 11 AND 20;
  • 單次掃描、優化器可利用索引順序、可並行、標準 SQL:2003 語法。
  • 生產環境強烈建議使用此寫法。

SQL Server 專屬:OFFSET/FETCH(2012+)

SELECT * FROM t_table
WHERE key = '123'
ORDER BY id
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

總結

  • 標準 SQL 分頁 = 相關子查詢計算序數,理解原理但不建議生產大量資料使用。
  • 現代資料庫請使用 ROW_NUMBER() / OFFSET/FETCH / LIMIT 等原生分頁語法。
  • 分頁必備條件:確定排序順序 + 唯一排序鍵 + 穩定篩選條件。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved