| 數據庫 | 分頁語法 | 關鍵字/函數 | 版本要求 |
|---|---|---|---|
| MySQL | LIMIT offset, rows | LIMIT | 所有版本 |
| PostgreSQL | LIMIT rows OFFSET offset | LIMIT/OFFSET | 所有版本 |
| Oracle | ROWNUM 子查詢 / OFFSET/FETCH | ROWNUM / OFFSET FETCH | 12c+ 支援標準語法 |
| SQL Server | ROW_NUMBER() / OFFSET/FETCH | ROW_NUMBER / OFFSET FETCH | 2005+ / 2012+ |
-- 前 10 行
SELECT * FROM T WHERE ... LIMIT 10;
-- 第 2 頁(每頁 10 行)
SELECT * FROM T WHERE ... LIMIT 10, 10; -- offset=10, rows=10
-- 或標準寫法
SELECT * FROM T WHERE ... LIMIT 10 OFFSET 10;
注意:深分頁(如 LIMIT 1000000, 10)需掃描並丟棄前 100 萬行,效能線性下降。優化:覆蓋索引 + 延遲關聯或 Keyset 分頁(WHERE Id > @LastId LIMIT 10)。
SELECT * FROM (
SELECT A.*, ROWNUM RN FROM (
SELECT * FROM Table_Name ORDER BY Sort_Col
) A WHERE ROWNUM <= 40
) WHERE RN >= 21; -- 第 21-40 行
WHERE ROWNUM <= 40 可提前終止排序,關鍵優化點。SELECT * FROM Table_Name
ORDER BY Sort_Col
OFFSET 20 ROWS FETCH NEXT 20 ROWS ONLY;
執行計劃等價於方案一,語法標準、可移植。
SELECT TOP 10 * FROM TestTable
WHERE Id NOT IN (SELECT TOP 20 Id FROM TestTable ORDER BY Id)
ORDER BY Id;
子查詢隨頁碼增長掃描量線性增大,深分頁極慢。
SELECT TOP 10 * FROM TestTable
WHERE Id > (SELECT MAX(Id) FROM (SELECT TOP 20 Id FROM TestTable ORDER BY Id) AS T)
ORDER BY Id;
利用索引求 MAX,避免 NOT IN 全掃描,效能顯著優於方案一。
使用 sp_cursoropen/fetch/close,適配任意查詢但開銷極大,僅作兜底。
SELECT * FROM (
SELECT ROW_NUMBER() OVER (ORDER BY Id) AS Rn, *
FROM TestTable
) T WHERE Rn BETWEEN 21 AND 30;
SELECT * FROM TestTable
ORDER BY Id
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
| 方案 | MySQL | Oracle | SQL Server |
|---|---|---|---|
| 首頁/淺分頁 | LIMIT 極快 | ROWNUM/OFFSET 快 | ROW_NUMBER/OFFSET 快 |
| 深分頁 (第 10 萬頁) | 線性變慢 | ROWNUM 仍可接受 | ROW_NUMBER 穩定 |
| 最佳優化 | Keyset 分頁 | ROWNUM 截斷排序 | 覆蓋索引 + 延遲關聯 |
-- 首頁
SELECT * FROM T ORDER BY Id LIMIT 20;
-- 後續頁(記住上一頁最大 Id)
SELECT * FROM T WHERE Id > @LastMaxId ORDER BY Id LIMIT 20;
LIMIT、Oracle ROWNUM、SQL Server ROW_NUMBER()。