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

SQL Server 2005+ 高效分頁存儲過程:支援多欄排序、無需主鍵、回傳總筆數

     編輯:關於SqlServer

專案開發中常遇到大量資料分頁需求。前端分頁雖能減少資料庫連線,但首次載入大量資料會佔用記憶體、增加網路傳輸。後端分頁將邏輯下推至資料庫,僅回傳當頁資料與總筆數,更適合大型系統。本文提供一個通用分頁預存程序,解決五大痛點:條件篩選、多欄排序、不依賴主鍵、回傳總記錄數、邏輯封裝於資料庫層。

預存程序完整碼

CREATE PROCEDURE [dbo].[FinalSortingAndPaging]
  @sqlStr   VARCHAR(2000) = 'SELECT DISTINCT h_year, z_periods, h_periods FROM FertilizerHeader WHERE 1=1',
  @sortStr  VARCHAR(50)   = 'h_year DESC, z_periods DESC',
  @pageIndex INT = 1,
  @pageSize  INT = 100
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @queryStr      NVARCHAR(2000),
          @queryRecordStr NVARCHAR(2000),
          @recordCount   INT;

  -- 1. 取得總筆數
  SET @queryRecordStr = 'SELECT @recordCount=COUNT(*) FROM (' + @sqlStr + ') AS c';
  EXEC sp_executesql @queryRecordStr, N'@recordCount INT OUTPUT', @recordCount OUTPUT;

  -- 2. 使用 ROW_NUMBER() 分頁
  SET @queryStr = 'WITH tempTable AS (
      SELECT *, ROW_NUMBER() OVER (ORDER BY ' + @sortStr + ') AS RowNumber
      FROM (' + @sqlStr + ') AS a
    )
    SELECT * FROM tempTable
    WHERE RowNumber BETWEEN ' + CAST((@pageIndex-1)*@pageSize + 1 AS VARCHAR(10)) +
    ' AND ' + CAST(@pageIndex * @pageSize AS VARCHAR(10));

  EXEC (@queryStr);
  RETURN @recordCount;
END

關鍵設計亮點

痛點解決方案
條件查詢分頁@sqlStr 直接傳入完整 WHERE 子句,動態組合
多欄排序@sortStr 獨立傳入 ORDER BY 片段,如 col1 DESC, col2 ASC
不依賴主鍵ROW_NUMBER() 配合任意排序欄位,無需身分識別欄
回傳總筆數先執行 COUNT(*) OVER 子查詢,透過 OUTPUT 參數回傳
邏輯封裝所有分頁邏輯在 SP 內完成,前端僅呼叫 SP

C# 呼叫範例

public DataSet FinalSortingAndPagingQuery(string sqlStr, string sortStr,
    int pageIndex, int pageSize, out int recordCount)
{
    var ds = new DataSet();
    try {
        using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["XXXX"].ConnectionString))
        using (var cmd = new SqlCommand("FinalSortingAndPaging", conn) { CommandType = CommandType.StoredProcedure })
        {
            cmd.Parameters.AddWithValue("@sqlStr", sqlStr);
            cmd.Parameters.AddWithValue("@sortStr", sortStr);
            cmd.Parameters.AddWithValue("@pageIndex", pageIndex);
            cmd.Parameters.AddWithValue("@pageSize", pageSize);
            var pRet = cmd.Parameters.Add("@recordCount", SqlDbType.Int);
            pRet.Direction = ParameterDirection.ReturnValue;

            var da = new SqlDataAdapter(cmd);
            da.Fill(ds);
            recordCount = (int)pRet.Value;
        }
    } catch { ds = null; recordCount = 0; }
    return ds;
}

使用限制與效能提醒

  • 適用版本:SQL Server 2005 及以上(需支援 ROW_NUMBER())。
  • 動態 SQL 風險:@sqlStr 由應用層組裝,務必嚴格參數化或白名單驗證,防止 SQL Injection。
  • 效能基準:1.5 萬筆測試約 0.158 ms;百萬筆以上建議加上覆蓋索引或改用 Keyset Pagination(游標式分頁)。
  • 排序欄位:@sortStr 必須為有效排序清單,不能包含 ORDER BY 關鍵字。

擴充建議

  1. 加入 @totalPages OUTPUT 直接回傳總頁數,減少前端計算。
  2. 支援 OFFSET ... FETCH NEXT(SQL 2012+)簡化語法。
  3. 整合快取機制:針對高頻、低變動查詢快取總筆數與首頁資料。

此 SP 在中小型專案實測穩定,歡迎針對大資料量場景優化並回饋。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved