仙桃市本地信息网

SQLServer中获取指定范围分页取数的两种方式

2026-04-19 23:10:05 浏览次数:0
详细信息

1. ROW_NUMBER() + CTE (推荐)

这是最常用且性能较好的分页方式,支持 SQL Server 2005 及以上版本。

-- 方式一:使用 ROW_NUMBER() + CTE
WITH PaginatedData AS (
    SELECT 
        ROW_NUMBER() OVER (ORDER BY CreateDate DESC) AS RowNum,
        UserID,
        UserName,
        Email,
        CreateDate
    FROM Users
    WHERE IsActive = 1  -- 可选的筛选条件
)
SELECT *
FROM PaginatedData
WHERE RowNum BETWEEN 11 AND 20  -- 获取第2页,每页10条
ORDER BY RowNum;

优点:

2. OFFSET FETCH (SQL Server 2012+)

这是 SQL Server 2012 引入的 ANSI SQL 标准语法,语法更简洁。

-- 方式二:使用 OFFSET FETCH
SELECT 
    UserID,
    UserName,
    Email,
    CreateDate
FROM Users
WHERE IsActive = 1  -- 可选的筛选条件
ORDER BY CreateDate DESC
OFFSET 10 ROWS       -- 跳过前10条(第1页)
FETCH NEXT 10 ROWS ONLY;  -- 取10条(第2页)

优点:

对比与选择建议

特性 ROW_NUMBER() + CTE OFFSET FETCH
版本支持 SQL Server 2005+ SQL Server 2012+
性能 良好 良好(2012+)
语法简洁性 中等
灵活性 高(可做复杂处理) 中等
标准性 非标准 ANSI SQL 标准

实用封装示例

1. 存储过程封装

CREATE PROCEDURE GetUsersByPage
    @PageIndex INT = 1,      -- 页码(从1开始)
    @PageSize INT = 10,       -- 每页条数
    @SortField NVARCHAR(50) = 'CreateDate',
    @SortOrder NVARCHAR(4) = 'DESC'
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @StartRow INT = (@PageIndex - 1) * @PageSize + 1;
    DECLARE @EndRow INT = @PageIndex * @PageSize;

    -- 动态排序需要用动态SQL,这里用 ROW_NUMBER()
    DECLARE @Sql NVARCHAR(MAX);
    SET @Sql = N'
    WITH PaginatedData AS (
        SELECT 
            ROW_NUMBER() OVER (ORDER BY ' + QUOTENAME(@SortField) + ' ' + @SortOrder + ') AS RowNum,
            UserID,
            UserName,
            Email,
            CreateDate
        FROM Users
        WHERE IsActive = 1
    )
    SELECT *
    FROM PaginatedData
    WHERE RowNum BETWEEN @StartRow AND @EndRow
    ORDER BY RowNum';

    EXEC sp_executesql @Sql, 
        N'@StartRow INT, @EndRow INT',
        @StartRow, @EndRow;
END

2. 获取总记录数 + 分页数据

-- 同时返回分页数据和总记录数
DECLARE @PageIndex INT = 2;
DECLARE @PageSize INT = 10;

-- 使用 OUTPUT 参数或额外查询获取总数
DECLARE @TotalCount INT;

SELECT @TotalCount = COUNT(*)
FROM Users
WHERE IsActive = 1;

WITH PaginatedData AS (
    SELECT 
        ROW_NUMBER() OVER (ORDER BY CreateDate DESC) AS RowNum,
        UserID,
        UserName,
        Email,
        CreateDate
    FROM Users
    WHERE IsActive = 1
)
SELECT 
    *,
    @TotalCount AS TotalCount
FROM PaginatedData
WHERE RowNum BETWEEN (@PageIndex - 1) * @PageSize + 1 
    AND @PageIndex * @PageSize;

性能优化建议

索引优化:确保 ORDER BY 和 WHERE 涉及的列有合适的索引 **避免 SELECT ***:只选择需要的列 参数化查询:防止 SQL 注入 大表分页:对于非常大的表,可以考虑使用键集分页
-- 键集分页(保持分页状态)
SELECT TOP 10 *
FROM Users
WHERE CreateDate < @LastSeenDate  -- 上一页最后一条的日期
ORDER BY CreateDate DESC;

选择建议

相关推荐