預存程序完整代碼
USE [Db_8za8za_2]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Paging]
@SqlStr nvarchar(4000), -- 查詢語句(如 select * from T_employee)
@CurrentPage int, -- 當前頁碼 (1-based)
@PageSize int -- 每頁筆數
AS
BEGIN
SET NOCOUNT ON; -- 避免干擾 SELECT 結果
DECLARE @CursorId int; -- 游標 ID
DECLARE @Rowcount int; -- 總筆數
DECLARE @PageCount int; -- 總頁數
-- 開啟游標並取得總筆數
EXEC sp_cursoropen @CursorId OUTPUT, @SqlStr,
@scrollopt = 1, -- KEYSET 游標
@ccopt = 1, -- READ_ONLY
@rowcount = @Rowcount OUTPUT;
-- 計算總頁數
SET @PageCount = CEILING(1.0 * @Rowcount / @PageSize);
-- 回傳分頁資訊(第一個結果集)
SELECT @PageCount AS 總頁數, @Rowcount AS 總行數, @CurrentPage AS 當前頁;
-- 邊界修正
IF (@CurrentPage > @PageCount) SET @CurrentPage = @PageCount;
IF (@CurrentPage <= 0) SET @CurrentPage = 1;
-- 計算游標絕對位置(1-based)
SET @CurrentPage = (@CurrentPage - 1) * @PageSize + 1;
-- 擷取分頁資料(第二個結果集)
EXEC sp_cursorfetch @CursorId, 16, @CurrentPage, @PageSize;
-- 關閉游標
EXEC sp_cursorclose @CursorId;
SET NOCOUNT OFF;
END
關鍵邏輯說明
- sp_cursoropen:建立伺服器端游標,
@scrollopt=1 為 KEYSET 游標(支援絕對定位),@ccopt=1 唯讀,透過 OUTPUT 參數取得總筆數 @Rowcount。
- CEILING(1.0 * @Rowcount / @PageSize):避免整數除法截斷,正確計算總頁數。
- 第一個結果集:回傳分頁資訊(總頁數、總筆數、當前頁),供呼叫端顯示分頁導航。
- 邊界保護:頁碼超過總頁數→最後一頁;小於等於 0→第一頁。
- sp_cursorfetch:
16 代表 FETCH_ABSOLUTE,從計算好的絕對位置擷取 @PageSize 筆資料。
- sp_cursorclose:釋放游標資源,避免洩漏。
使用注意事項
- @SqlStr 必須為單一 SELECT 語句,且不含 ORDER BY(或由呼叫端保證順序)。
- 游標方式適合中小資料量;大資料量建議改用
ROW_NUMBER() OVER (ORDER BY ...) 視窗函數(SQL Server 2005+)效能更佳。
- Java 呼叫端需正確處理兩個結果集,參考下一篇(ID: 110625)。