SQL Server 2005 引入 ROW_NUMBER() OVER (ORDER BY ...) 視窗函數,提供標準、高效的分頁查詢語法,取代舊版複雜的 TOP + NOT IN 或 SET ROWCOUNT 技巧。
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY CreditCardID) AS RowNum, *
FROM Sales.CreditCard
) AS T
WHERE RowNum BETWEEN 1 AND 50; -- 第 1 頁,每頁 50 筆
CREATE PROCEDURE usp_PageQuery_Standard
@PageNumber INT = 1,
@PageSize INT = 20,
@OrderBy SYSNAME = 'ID',
@WhereClause NVARCHAR(MAX) = ''
AS
BEGIN
SET NOCOUNT ON;
DECLARE @SQL NVARCHAR(MAX), @Start INT = (@PageNumber - 1) * @PageSize + 1,
@End INT = @PageNumber * @PageSize;
SET @SQL = N'
WITH Numbered AS (
SELECT ROW_NUMBER() OVER (ORDER BY ' + QUOTENAME(@OrderBy) + N') AS RowNum, *
FROM TargetTable
' + CASE WHEN @WhereClause <> '' THEN N'WHERE ' + @WhereClause ELSE N'' END + N'
)
SELECT * FROM Numbered WHERE RowNum BETWEEN ' + CAST(@Start AS NVARCHAR(10)) + N' AND ' + CAST(@End AS NVARCHAR(10)) + N';';
EXEC sp_executesql @SQL;
END
若為無限捲動/下一頁場景,改用鍵值集分頁效能更佳:
-- 第一頁
SELECT TOP 20 * FROM TargetTable ORDER BY ID;
-- 後續頁(記住上一頁最大 ID)
SELECT TOP 20 * FROM TargetTable WHERE ID > @LastMaxID ORDER BY ID;
| 版本 | 分頁語法 | 備註 |
|---|---|---|
| SQL 2000 | TOP + NOT IN / SET ROWCOUNT | 效能差、語法繁瑣 |
| SQL 2005/2008/R2 | ROW_NUMBER() OVER | 標準化、效能尚可 |
| SQL 2012+ | OFFSET ... ROWS FETCH NEXT ... ROWS ONLY | ANSI 標準、最佳化器深度支援 |
SQL 2005 起請優先使用 ROW_NUMBER(),代碼更清晰、維護更容易、效能更可預測。