分頁查詢是資料庫應用核心需求,但不同資料庫語法差異極大。本文彙整 MySQL、SQL Server(2000/2005/2012+)、Oracle 三大主流資料庫的分頁寫法,含原理解析、效能比較與最佳實務。
-- 前 10 筆
SELECT * FROM table_name WHERE ... LIMIT 10;
-- 或 LIMIT 0, 10
-- 第 11-30 筆(每頁 20 筆,第 2 頁)
SELECT * FROM table_name WHERE ... LIMIT 10, 20;
-- 通用公式:LIMIT (頁碼-1)*頁大小, 頁大小
OFFSET ... LIMIT ... 語法SELECT TOP 10 * FROM table_name
WHERE id NOT IN (SELECT TOP 20 id FROM table_name ORDER BY id)
ORDER BY id
改良版:MAX(id) 分水嶺法(需主鍵唯一、非複合主鍵):
SELECT TOP @pageSize *
FROM table_name
WHERE id > (
SELECT MAX(id) FROM (
SELECT TOP ((@pageNum-1)*@pageSize) id FROM table_name ORDER BY id
) AS T
)
ORDER BY id
WITH Paged AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY id) AS rn
FROM table_name
)
SELECT * FROM Paged
WHERE rn BETWEEN (@pageNum-1)*@pageSize + 1 AND @pageNum*@pageSize
ORDER BY rn;
OVER (ORDER BY ...) 定義排序依據,支援複合主鍵SELECT * FROM table_name
ORDER BY id
OFFSET (@pageNum-1)*@pageSize ROWS
FETCH NEXT @pageSize ROWS ONLY;
SELECT * FROM (
SELECT t.*, ROW_NUMBER() OVER (ORDER BY t.id) rn
FROM table_name t
)
WHERE rn BETWEEN 21 AND 40;
SELECT * FROM (
SELECT t.*, ROWNUM rn
FROM table_name t
WHERE ROWNUM <= 40
)
WHERE rn >= 21;
ROWNUM <= 40 讓 Oracle 提前停止掃描,減少 I/OORDER BY 時速度極快,但結果順序不確定ORDER BY,外層再套 ROWNUM建議加上唯一鍵作為第二排序鍵:ORDER BY id, unique_col。
| 資料庫 | 推薦寫法 | 適用版本 | 備註 |
|---|---|---|---|
| MySQL | LIMIT / OFFSET-FETCH | 全版本 / 8.0+ | 簡潔高效 |
| SQL Server | OFFSET-FETCH | 2012+ | 標準語法,最佳效能 |
| SQL Server | ROW_NUMBER() | 2005+ | 相容舊版 |
| Oracle | 雙層 ROWNUM | 全版本 | 大資料量首選 |
| Oracle | ROW_NUMBER() | 10g+ | 需複雜排序時 |
WHERE id > last_seen_id ORDER BY id LIMIT 20SELECT *,僅查詢所需欄位COUNT(*))可分離快取,避免每頁重複計算掌握各資料庫分頁寫法差異,能針對不同環境寫出高效、可維護的分頁邏輯。