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

主流數據庫分頁查詢寫法大全:SQL Server、Oracle、MySQL、PostgreSQL

     編輯:關於SqlServer

分頁是 MIS/Web 系統核心需求,一次性拉取全量數據會撐爆內存與網絡。各數據庫方言差異大,本文匯總 SQL Server、Oracle、MySQL、PostgreSQL 四大主流庫的標準分頁寫法,並給出生產環境優化建議。

1. SQL Server

2012+ 標準語法(推薦)

SELECT col1, col2
FROM dbo.TableName
ORDER BY PK_Column
OFFSET @PageSize * (@PageNum - 1) ROWS
FETCH NEXT @PageSize ROWS ONLY;
  • OFFSET/FETCH 符合 ANSI SQL:2008,計畫穩定、可讀性強。
  • 需搭配 ORDER BY 且順序唯一(建議含 PK),否則結果不確定。

2005/2008 兼容寫法(CTE + ROW_NUMBER)

WITH CTE AS (
    SELECT col1, col2,
           ROW_NUMBER() OVER (ORDER BY PK_Column) AS rn
    FROM dbo.TableName
)
SELECT col1, col2
FROM CTE
WHERE rn BETWEEN @StartRow AND @EndRow;

舊版 Top 雙重嵌套(不推薦,深分頁效能差)

SELECT *
FROM (
    SELECT TOP @PageSize *
    FROM (
        SELECT TOP (@PageSize * @PageNum) *
        FROM TableName
        ORDER BY PK_Column DESC
    ) t1
    ORDER BY PK_Column ASC
) t2;

2. Oracle

12c+ 標準語法

SELECT col1, col2
FROM TableName
ORDER BY PK_Column
OFFSET :offset ROWS FETCH NEXT :pageSize ROWS ONLY;

11g 及以下經典寫法(ROWNUM 兩層嵌套)

SELECT *
FROM (
    SELECT ROWNUM rn, t1.*
    FROM (
        SELECT col1, col2
        FROM TableName
        ORDER BY PK_Column
    ) t1
    WHERE ROWNUM <= :endRow
) t2
WHERE t2.rn >= :startRow;

關鍵點:內層 ORDER BY 必須在 ROWNUM 過濾之前,否則順序錯亂。

3. MySQL / MariaDB

標準 LIMIT 語法

SELECT col1, col2
FROM TableName
ORDER BY PK_Column
LIMIT @offset, @pageSize;  -- 或 LIMIT @pageSize OFFSET @offset
  • LIMIT M, N:跳過 M 行,取 N 行(M 從 0 開始)。
  • 深分頁(大 OFFSET)效能急劇下降,優化見下文。

4. PostgreSQL

標準 OFFSET/LIMIT(兼容 SQL:2008)

SELECT col1, col2
FROM TableName
ORDER BY PK_Column
LIMIT @pageSize OFFSET @offset;
  • 支援 FETCH FIRST @pageSize ROWS ONLY 標準語法。
  • 深分頁同樣存在 OFFSET 掃描開銷。

深分頁效能優化通用策略

策略原理適用場景代碼示例
Keyset Pagination (Seek Method) 記住上一頁最大 PK,下頁 WHERE pk > @lastPk ORDER BY pk LIMIT N 單向翻頁(無跳頁需求),PK 單調遞增 SELECT * FROM t WHERE id > 1000 ORDER BY id LIMIT 20;
延遲關聯 先只查 PK 分頁,再 JOIN 回表取明細 寬表、多列查詢、覆蓋索引無法覆蓋所有列 SELECT t.* FROM t JOIN (SELECT id FROM t ORDER BY id LIMIT 20 OFFSET 10000) tmp USING(id);
覆蓋索引 索引包含所有 SELECT 列,避免回表 高頻分頁查詢,列數較少 CREATE INDEX idx_cov ON t (pk) INCLUDE (col1, col2);
緩存首頁/熱頁 Redis 緩存前 N 頁 JSON,直讀返回 首頁、熱門列表、實時性要求秒級 —

生產環境檢查清單

  • [ ] 所有分頁查詢有確定性 ORDER BY(含 PK/唯一鍵)。
  • [ ] 深分頁(> 100 頁)改用 Keyset Pagination 或延遲關聯。
  • [ ] 高頻分頁建立覆蓋索引,EXPLAIN 驗證 Using index。
  • [ ] 參數化查詢復用計畫,防注入。
  • [ ] 總數統計 COUNT(*) 走覆蓋索引或緩存,避免全表掃描。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved