分頁查詢是 Web 應用核心需求。本文整理 MySQL、SQL Server(2000/2005)、Oracle 三大主流資料庫的分頁寫法,並分析效能優劣。
SELECT * FROM `table` WHERE ... LIMIT 10; -- 前 10 筆
SELECT * FROM `table` WHERE ... LIMIT 0, 10; -- 前 10 筆(相同)
SELECT * FROM `table` WHERE ... LIMIT 10, 20; -- 第 11~30 筆(offset 10, 取 20 筆)
基本寫法(含 NOT IN 缺點):
SELECT TOP 10 * FROM sql
WHERE code NOT IN (SELECT TOP 20 code FROM TestTable ORDER BY id)
ORDER BY id
缺點: NOT IN 效能差,資料量大時明顯拖慢。
SELECT TOP 頁大小 *
FROM table1
WHERE id > (
SELECT MAX(id) FROM (
SELECT TOP ((頁碼-1)*頁大小) id FROM table1 ORDER BY id
) AS T
)
ORDER BY id
SELECT TOP 10 * FROM (
SELECT TOP 10 ROW_NUMBER() OVER (ORDER BY ReportID) AS RowNo
FROM TABLE
) AS A
WHERE RowNo > 頁碼*10
ROW_NUMBER() OVER (ORDER BY ...) 產生連續行號SELECT * FROM (
SELECT t.*, ROW_NUMBER() OVER (ORDER BY t.id) AS rowno
FROM TABLE1
)
WHERE rowno BETWEEN 21 AND 40;
SELECT * FROM (
SELECT t.*, ROWNUM AS rowno FROM TABLE1
)
WHERE rowno BETWEEN 10 AND 20;
ORDER BY,檢索速度更快,資料量大時優勢明顯ROWNUM 是查詢結果集產生時的順序,若需排序請在子查詢中完成Oracle 10g+ 中慎用帶 ORDER BY 的分頁,可能導致相同記錄出現在不同頁面(資料抖動)。
| 資料庫 | 推薦語法 | 關鍵點 |
|---|---|---|
| MySQL | LIMIT offset, rows | 語法最簡潔,效能佳 |
| SQL Server 2000 | TOP + MAX(id) 子查詢 | 需唯一主鍵,避免 NOT IN |
| SQL Server 2005+ | ROW_NUMBER() OVER() | 支援複合鍵,標準寫法 |
| Oracle | ROWNUM 子查詢 | 無 ORDER BY 開銷,速度最快 |