带你快速搞懂SQL Server里那些分页查询到底咋写和用法
- 问答
- 2025-12-29 16:01:40
- 2
行,那咱们就直接开整,聊透 SQL Server 里分页查询那点事儿,这玩意儿说白了就是当你的数据成千上万条,没法儿一次性全甩给用户看的时候,用来“一页一页”显示数据的技术,就像你看一本很厚的书,不可能一次看完,得翻页,对吧?数据库里的分页也是这个理儿。
在 SQL Server 的不同版本里,干这个活儿的“工具”不太一样,咱们就按时间顺序,从老办法到新办法,一个一个掰扯清楚。
最早的“土办法”:用 TOP 和临时表
在 SQL Server 2005 以前,还没啥专门的分页命令,程序员们就想出了一个挺聪明但有点绕的招数,这个办法的核心思路是先倒序,再正序。
假设我们有个表叫 Orders(订单表),我们想按 OrderID 排序,看第二页的数据,假设一页显示 10 行。
步骤是这样的:
- 先取出前 N 页的所有数据: 比如我要看第二页(每页10条),那我就得先把前 20 条 (
2页 * 10条/页) 数据找出来。SELECT TOP 20 * FROM Orders ORDER BY OrderID ASC
- 再把取出来的这些数据倒序排列: 这样,我们真正想要的那一页(也就是第11到第20条)反而会跑到最前面来。
- 最后从倒序的结果里取前 M 条: 这时我们再取前 10 条,就是我们想要的第二页内容了。
合起来写成一个句子就是:
SELECT TOP 10 * FROM (
SELECT TOP 20 * FROM Orders ORDER BY OrderID ASC
) AS TempTable ORDER BY OrderID DESC
注意: 你最后可能还得再套一层排序,把顺序给正回来。
咋用咋想: 这方法就像是你想把一摞卡片中的第11张到第20张拿出来,你先数出前20张,然后把整摞20张翻个面,这时原来的第20张就变成了第一张,你再从最上面数10张,这10张就是原来的第11到第20张,最后你可能还得把这10张的顺序再翻回去。
这个方法虽然能实现,但写起来麻烦,理解起来也费劲,尤其是排序条件复杂的时候,很容易把自己绕晕。
划时代的进步:ROW_NUMBER() 窗口函数
到了 SQL Server 2005,微软带来了一个神器——窗口函数,ROW_NUMBER() 就是用来分页的“大杀器”,它的作用是给查询出来的每一行都加一个连续的数字编号。
基本语法:
SELECT *, ROW_NUMBER() OVER (ORDER BY 某个字段) AS RowNum FROM 表名
这个 RowNum 就是我们给数据编的号,从1开始。
用到分页上: 我们知道第几页、每页多少条,就能算出我们需要哪些编号的数据。
- 第1页:编号 1 到 10
- 第2页:编号 11 到 20
- 第N页:编号
(N-1)*每页条数 + 1到N*每页条数
那我们只要把带有编号的查询结果当成一个临时表,再从里面按编号范围取数据就行了。
举个例子,查第二页(每页10条):
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY OrderID) AS RowNum
FROM Orders
) AS NumberedOrders
WHERE RowNum BETWEEN 11 AND 20
咋用咋想:
这就清晰多了!就像给全班同学按身高排好队,然后从1开始报数,老师想叫第11号到第20号的同学出列,直接按号码喊就行了,非常直观。ROW_NUMBER() 就是那个“报数”的人。
这个方法一出来,很快就成了 SQL Server 分页的标准写法,因为它又简单又强大,排序规则写在 OVER 子句里也很灵活。
现在的“官方推荐”:OFFSET-FETCH 子句
时间来到 SQL Server 2012,微软觉得分页这么常见的需求,应该有个更直接的语法,他们在 ORDER BY 子句后面增加了 OFFSET 和 FETCH 这两个关键字,这可以说是最像“人话”的分页写法了。
语法结构:
SELECT 列名 FROM 表名 ORDER BY 某个字段 OFFSET 跳过的行数 ROWS FETCH NEXT 获取的行数 ROWS ONLY
直接看例子:
-
查询第一页(每页10条): 不需要跳过任何行。
SELECT * FROM Orders ORDER BY OrderID OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY
-
查询第二页(每页10条): 需要跳过第一页的10条数据。
SELECT * FROM Orders ORDER BY OrderID OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
-
查询第N页(每页M条): 需要跳过
(N-1) * M条数据。SELECT * FROM Orders ORDER BY OrderID OFFSET (页码-1)*每页条数 ROWS FETCH NEXT 每页条数 ROWS ONLY
咋用咋想: 这简直就是把分页的需求直接翻译成了 SQL 语句!“OFFSET”跳过”,“FETCH”取”,老板跟你说:“跳过前20条记录,然后给我接下来的10条”,你直接就能写出代码,无比简单明了!
到底用哪个?
现在你明白了吧,SQL Server 的分页进化史就是一个从“绞尽脑汁”到“直抒胸臆”的过程。
- 如果你用的 SQL Server 是 2012 或更新版本,别犹豫,直接用
OFFSET-FETCH,这是性能最好、写法最简洁的官方方案。 - 如果你的数据库版本是 2005 到 2008 R2,那你主要的选择就是
ROW_NUMBER()函数,它依然非常强大和有效。 - 至于最早的
TOP嵌套查询,了解一下就行,知道前辈们是这么过来的,但现在除非极特殊情况,否则已经没必要用了。
最后啰嗦一句,不管用哪种方法,ORDER BY(排序)都是至关重要的,你必须告诉数据库一个明确的排序规则,分页才有意义,不然数据库每次返回的数据顺序可能都不一样,你的分页就全乱套了。
希望这么一趟顺下来,你能彻底搞懂 SQL Server 的分页到底该怎么玩!

本文由度秀梅于2025-12-29发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/70740.html
