如何在 SQL Server 2005 中对结果进行分页?
我在 SQL Server 2000 中尝试过,但没有可靠的方法来做到这一点。我现在想知道 SQL Server 2005 是否有任何内置方法?
我所说的分页是指,例如,如果我按用户名列出用户,我希望能够只返回前 10 条记录,然后是接下来的 10 条记录,依此类推。
任何帮助将非常感激。
如何在 SQL Server 2005 中对结果进行分页?
我在 SQL Server 2000 中尝试过,但没有可靠的方法来做到这一点。我现在想知道 SQL Server 2005 是否有任何内置方法?
我所说的分页是指,例如,如果我按用户名列出用户,我希望能够只返回前 10 条记录,然后是接下来的 10 条记录,依此类推。
任何帮助将非常感激。
你可以使用the Row_Number()
函数。其用法如下:
SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users
它将从中产生一个结果集,其中包含一个RowID
可用于在其间进行分页的字段。
SELECT *
FROM
( SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users
) As RowResults
WHERE RowID Between 5 AND 10
ETC
如果您试图在一个语句中获取它(总数加上分页)。您可能需要探索 SQL Server 对 partition by 子句的支持(ANSI SQL 术语中的窗口函数)。在 Oracle 中,语法就像上面使用 row_number() 的示例一样,但我还添加了一个 partition by 子句来获取分页中返回的每一行包含的总行数(总行数为 1,262):
SELECT rn, total_rows, x.OWNER, x.object_name, x.object_type
FROM (SELECT COUNT (*) OVER (PARTITION BY owner) AS TOTAL_ROWS,
ROW_NUMBER () OVER (ORDER BY 1) AS rn, uo.*
FROM all_objects uo
WHERE owner = 'CSEIS') x
WHERE rn BETWEEN 6 AND 10
请注意,我有 where owner = 'CSEIS' 并且我的分区在所有者上。所以结果是:
RN TOTAL_ROWS OWNER OBJECT_NAME OBJECT_TYPE
6 1262 CSEIS CG$BDS_MODIFICATION_TYPES TRIGGER
7 1262 CSEIS CG$AUS_MODIFICATION_TYPES TRIGGER
8 1262 CSEIS CG$BDR_MODIFICATION_TYPES TRIGGER
9 1262 CSEIS CG$ADS_MODIFICATION_TYPES TRIGGER
10 1262 CSEIS CG$BIS_LANGUAGES TRIGGER
对此接受的答案实际上对我不起作用......我不得不再跳一圈才能让它工作。
当我尝试答案时
SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users
WHERE RowID Between 0 AND 9
它失败了,抱怨它不知道 RowID 是什么。
我不得不将它包装在这样的内部选择中:
SELECT *
FROM
(SELECT
Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users
) innerSelect
WHERE RowID Between 0 AND 9
然后它起作用了。
当我需要进行分页时,我通常也会使用临时表。您可以使用输出参数来返回记录总数。select 中的 case 语句允许您对特定列上的数据进行排序,而无需求助于动态 SQL。
--Declaration--
--Variables
@StartIndex INT,
@PageSize INT,
@SortColumn VARCHAR(50),
@SortDirection CHAR(3),
@Results INT OUTPUT
--Statements--
SELECT @Results = COUNT(ID) FROM Customers
WHERE FirstName LIKE '%a%'
SET @StartIndex = @StartIndex - 1 --Either do this here or in code, but be consistent
CREATE TABLE #Page(ROW INT IDENTITY(1,1) NOT NULL, id INT, sorting_1 SQL_VARIANT, sorting_2 SQL_VARIANT)
INSERT INTO #Page(ID, sorting_1, sorting_2)
SELECT TOP (@StartIndex + @PageSize)
ID,
CASE
WHEN @SortColumn='FirstName' AND @SortDirection='ASC' THEN CAST(FirstName AS SQL_VARIANT)
WHEN @SortColumn='LastName' AND @SortDirection='ASC' THEN CAST(LastName AS SQL_VARIANT)
ELSE NULL
END AS sort_1,
CASE
WHEN @SortColumn='FirstName' AND @SortDirection='DES' THEN CAST(FirstName AS SQL_VARIANT)
WHEN @SortColumn='LastName' AND @SortDirection='DES' THEN CAST(LastName AS SQL_VARIANT)
ELSE NULL
END AS sort_2
FROM (
SELECT
CustomerId AS ID,
FirstName,
LastName
FROM Customers
WHERE
FirstName LIKE '%a%'
) C
ORDER BY sort_1 ASC, sort_2 DESC, ID ASC;
SELECT
ID,
Customers.FirstName,
Customers.LastName
FROM #Page
INNER JOIN Customers ON
ID = Customers.CustomerId
WHERE ROW > @StartIndex AND ROW <= (@StartIndex + @PageSize)
ORDER BY ROW ASC
DROP TABLE #Page
这是我为分页所做的:我所有需要分页的大查询都被编码为插入到临时表中。临时表有一个身份字段,其行为方式与上面提到的 row_number() 类似。我将临时表中的行数存储在输出参数中,以便调用代码知道总共有多少条记录。调用代码还指定它想要哪个页面,以及每页有多少行,这些都是从临时表中选择出来的。
这样做的好处是我还有一个“导出”链接,它允许您从我的应用程序中每个网格上方以 CSV 格式返回的报告中获取所有行。此链接使用相同的存储过程:您只需返回临时表的内容,而不是执行分页逻辑。这安抚了讨厌分页,想要查看所有内容,并希望以百万种不同方式对其进行排序的用户。