實務上常需一個彈性分頁 SP,支援單表/多表、指定欄位、排序、分組、條件篩選。本文提供完整版 Com_Pagination,採動態 SQL 組裝 + ROW_NUMBER() 窗口函數實作。
| 參數 | 型別 | 說明 |
|---|---|---|
| @TotalCount | INT OUTPUT | 總筆數 |
| @TotalPage | INT OUTPUT | 總頁數 |
| @Table | NVARCHAR(1000) | 查詢表(可含 JOIN,如 Person p LEFT JOIN TE a ON a.PID=p.Id) |
| @Column | NVARCHAR(1000) | 查詢欄位(可為 * 或 a.*) |
| @OrderColumn | NVARCHAR(100) | 排序欄位 |
| @GroupColumn | NVARCHAR(150) | 分組欄位(@Group=1 時生效) |
| @PageSize | INT | 每頁筆數 |
| @CurrentPage | INT | 目前頁碼(1-based) |
| @Group | TINYINT | 是否分組(0/1) |
| @Condition | NVARCHAR(4000) | WHERE 條件(含 AND,如 a.pid=2) |
TOP @PageSize。ROW_NUMBER() OVER (ORDER BY ...) 產生序號,再 BETWEEN 篩選頁碼區間。COUNT(*) ... GROUP BY 計算總筆數,查詢同樣加 GROUP BY。sp_executesql 取得 @TotalCount,再 EXEC(@strSql) 回傳資料。CREATE PROCEDURE [dbo].[Com_Pagination]
@TotalCount INT OUTPUT, @TotalPage INT OUTPUT,
@Table NVARCHAR(1000), @Column NVARCHAR(1000),
@OrderColumn NVARCHAR(100), @GroupColumn NVARCHAR(150),
@PageSize INT, @CurrentPage INT, @Group TINYINT,
@Condition NVARCHAR(4000)
AS
BEGIN
DECLARE @PageCount INT, @strSql NVARCHAR(4000), @strCount NVARCHAR(1000), @strOrderType NVARCHAR(1000);
SET @PageCount = @PageSize * (@CurrentPage - 1);
SET @strOrderType = ' ORDER BY ' + @OrderColumn + ' ';
-- 動態組裝統計與查詢 SQL(略,詳見原文完整版)
-- 關鍵:第一頁用 TOP,其他頁用 ROW_NUMBER() BETWEEN
EXEC sp_executesql @strCount, N'@TotalCount INT OUTPUT', @TotalCount OUTPUT;
IF @TotalCount > 2000 SET @TotalCount = 2000; -- 安全上限
SET @TotalPage = CASE WHEN @TotalCount % @PageSize = 0
THEN @TotalCount / @PageSize
ELSE @TotalCount / @PageSize + 1 END;
SET NOCOUNT ON; EXEC (@strSql); SET NOCOUNT OFF;
END
DECLARE @TotalCount INT, @TotalPage INT;
EXEC Com_Pagination
@TotalCount OUTPUT, @TotalPage OUTPUT,
'Person p LEFT JOIN TE a ON a.PID=p.Id', -- 多表
'a.*', 'p.ID', 'p.ID', 2, 1, 0, 'a.pid=2';
SELECT @TotalCount AS TotalCount, @TotalPage AS TotalPage;
@Condition 更安全(此範例為教學簡化)。TOP (2000) 為保護機制,避免 ROW_NUMBER 掃描過大範圍;依實際資料量調整。OFFSET ... FETCH 簡化語法。此 SP 適合快速建立後台管理分頁 API,減少重複造輪子。