SQLServer数据库分页
以 项目表 PM_Project 为例。
PM_Project 全部内容如下(共6条数据):

一、Top – Not In - Top 方式分页
直接的,原始的,不采用函数,纯手动挡。
分步探索过程:
采用的最直接做法就是使用两个Top来实现。
DECLARE @pageSize INT =4,@pageIndex INT =1
BEGIN
SELECT TOP (@pageSize)
*
FROM ( SELECT TOP (@pageSize * @pageIndex)
*
FROM PM_Project
ORDER BY Id DESC --- 内查询倒序
) AS temp
ORDER BY Id ---外查询正序, 内外查询顺序不一致即可
END
GO
结果:

乍一看是没有问题的,但是仔细一看会发现其中存在的问题。当符合条件的纪录集小于每页记录数时,没有问题,但是当大于就有问题了。
例如上边代码,实际满足条件的是6条,即全部满足(因为根本就没加条件)。第一页是没有问题的,但是第二页就有问题了。现在共6条数据,每页4条,按理说第二页应该只有2条。但是使用如上的方法,每次都会返回4条记录。
当pageIndex =2 时,结果如下:

沿用上面的思路,把代码修改为了采用三层查询,最内一层查询所有满足条件的数据,然后第二层选择Top PageSize个所有NOT IN 第一层数据中的数据即可,因为使用了NOT IN所以不存在第一种方法中的bug
DECLARE @pageSize INT =4,@pageIndex INT =2 ---直接看第二页
BEGIN SELECT *
FROM PM_Project
WHERE Id IN (
SELECT TOP ( @pageSize )
Id
FROM PM_Project
WHERE Id NOT IN ( SELECT TOP ( @pageSize * (@pageIndex-1) )---去除本页之前的所有id
Id
FROM PM_Project
ORDER BY Id)
ORDER BY PM_Project.Id)
ORDER BY PM_Project.Id ASC END
GO
结果:

二、ROW_NUMBER()的方式实现分页
语法:
ROW_NUMBER ( ) OVER ( [ PARTITION BY value_expression , ... [ n ] ] order_by_clause )
分步过程:
首先查询全部满足条件的数据,并使用 ROW_NUMBER() 函数,可以根据给定好的排序字段规则,为查询结果生成记录序号。
SELECT ROW_NUMBER() OVER (ORDER BY id) rownum,
*
FROM PM_Project
结果:(共6条数据)

然后用TOP()函数取出一页数据
DECLARE @pageSize INT =4,@pageIndex INT =1 ------每页4条,第一页
BEGIN SELECT TOP(@pageSize*@pageIndex)
ROW_NUMBER() OVER (ORDER BY id) rownum,
*
FROM PM_Project
END
GO
这样取第一页还是可以的,但是往后就会越来越多。现在将上边的查询作为内查询,再外查询中通过条件来控制获取页数问题。
策略很简单,首先我们选取包含要查页的数据,然后使用ROW_NUMER函数进行编号, 然后在外查询中指定rownum大于页起始记录即可。这种方式简单快捷。
DECLARE @pageSize INT =4,@pageIndex INT =2 ------每页4条,第二页
BEGIN
SELECT*FROM
(
SELECT TOP(@pageSize*@pageIndex)
ROW_NUMBER() OVER (ORDER BY id) rownum,*
FROM PM_Project
)temp
WHERE temp.rownum>(@pageSize*(@pageIndex-1))
END
GO
查询第二页的结果:

在 Sql Server 2000 之后的版本中,ROW_NUMBER() 这种分页方式一直都是很不错的,比起之前的游标分页,性能好了很多,因为 ROW_NUMBER() 并不会引起全表扫表,但是,语法比较复杂,并且,随着页码的增加,性能也越来越差。
三、使用CTE(common_table_expression,公用表表达式)的方式
使用很简单,就是把内查询放在CTE 里面。
DECLARE @pageSize INT =4,@pageIndex INT =2
BEGIN
WITH temp
AS ( SELECT TOP ( @pageSize * @pageIndex )
ROW_NUMBER() OVER ( ORDER BY id) AS rownum ,
*
FROM PM_Project
)
SELECT *
FROM temp
WHERE temp.rownum > ( @pageSize * ( @pageIndex - 1 ) )
ORDER BY temp.Id
END
GO
结果:

四、使用 OFFSET FETCH 子句分页
语法:
OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }
FETCH { FIRST | NEXT } { integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY
从语法可以看出来 两个方法 后面不但能接 intege 类型的参数,还能接 表达式的,比如 1*2 +3 之类的,同时, Row 或者 Rows 是不区分大小写和单复数的。
SQL Server 2012及以后版本支持。
例句:
DECLARE @pageSize INT =4,@pageIndex INT =2
BEGIN SELECT*FROM PM_Project
ORDER BY Id
OFFSET ( @pageSize * ( @pageIndex - 1 )) ROWS
FETCH NEXT @pageSize ROWS ONLY END
GO
结果:

性能对比:
SQLServer数据库分页的更多相关文章
- Sqlserver数据库分页查询
Sqlserver数据库分页查询一直是Sqlserver的短板,闲来无事,想出几种方法,假设有表ARTICLE,字段ID.YEAR...(其他省略),数据53210条(客户真实数据,量不大),分页查询 ...
- MySQL、SqlServer、Oracle三大主流数据库分页查询
在这里主要讲解一下MySQL.SQLServer2000(及SQLServer2005)和ORCALE三种数据库实现分页查询的方法.可能会有人说这些网上都有,但我的主要目的是把这些知识通过我实际的应用 ...
- 【转载】Sqlserver数据库中无自增Id的情况下使用ROW_NUMBER()函数进行数据分页
在Sqlserver数据库中,如果查询表中含有自增长Id列,一般会采用select Top的方式来数据的分页操作.而实际上很多数据表设计的时候,不一定含有自增长Id列,那么数据库没有Id自增列的时候要 ...
- mysql / sqlserver / oracle 常见数据库分页
空闲时间里用着mysql学习开发测试平台和测试用具, 在公司里将可用的测试平台部署,将数据库换成sqlserver 巴望着能去用oracle的公司 mysql中的分页 limit是mysql的语法se ...
- MySQL、SqlServer、Oracle三大主流数据库分页查询 (MySQL分页不能用top,因为不支持)
一. MySQL 数据库 分页查询MySQL数据库实现分页比较简单,提供了 LIMIT函数.一般只需要直接写到sql语句后面就行了.LIMIT子 句可以用来限制由SELECT语句返回过来的数据数量,它 ...
- 浅谈SQL Server数据库分页
数据库分页是老生常谈的问题了.如果使用ORM框架,再使用LINQ的话,一个Skip和Take就可以搞定.但是有时由于限制,需要使用存储过程来实现.在SQLServer中使用存储过程实现分页的已经有很多 ...
- sqlserver 存储过程分页管理
-- =============================================-- Author: <Author:刘畅>-- Create date: <Cre ...
- Oracle、MySql、SQLServer数据分页查询
看过此博文后Oracle.MySql.SQLServer 数据分页查询,在根据公司的RegionRes表格做出了 SQLserver的分页查询语句: 别名.字段 FROM( SELECT row_nu ...
- SQL多表连接查询以及mysql数据库、sqlserver数据库常见不同点
mysql数据库表及数据准备语句: USE test; DROP TABLE IF EXISTS `teacher_table`; DROP TABLE IF EXISTS `student_tabl ...
随机推荐
- Spring的AOP开发入门,Spring整合Junit单元测试(基于ASpectJ的XML方式)
参考自 https://www.cnblogs.com/ltfxy/p/9882430.html 创建web项目,引入jar包 除了基本的6个Spring开发的jar包外,还要引入aop开发相关的四个 ...
- Java监听器Listener使用详解
监听器用于监听web应用中某些对象.信息的创建.销毁.增加,修改,删除等动作的发生,然后作出相应的响应处理.当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法.常用于统计在线人数和在线用 ...
- jsp 或 php 等view之中使用javascript简单处理的使用技巧
前端人员在jsp,php等后台mvc之的coding之时,前端人员常常需要一些少量的数据处理,直接使用js的方法无疑是开销最小的.使用的方法 使用在标签之中嵌套script标签,使用document. ...
- vue-router 管理视图详解
什么是路由 在web开发中,路由是指根据url分配到对应的处理程序,当访问不同的url就会切换到对应的处理程序 在vue中一个url对应的就是一个组件,当访问不同的url,对应的组件就会呈现到页面中 ...
- Apache Shiro对象概念
#,Authentication,认证,也就是验证用户的身份,就是确定你是不是你,比如通过用户名.密码的方式验证,或者某些第三方认证,比如微信认证. #,Authorization,授权,也叫访问控制 ...
- 自然语言处理之word2vec
在word2vec出现之前,自然语言处理经常把字词转为one-hot编码类型的词向量,这种方式虽然非常简单易懂,但是数据稀疏性非常高,维度很多,很容易造成维度灾难,尤其是在深度学习中:其次这种词向量中 ...
- 【css】常用css
常用css--------下三角 常用css--------闪动效果 css #shandongFlash { width:100px; height:100px; background:#f8b55 ...
- ④---在Eclipse中导入GIT项目
Eclipse中导入GIT项目 以下将为大家介绍如何在Eclipse中导入GIT项目. 一.在Eclipse中安装GIT 1首先打开Eclipse,然后点击Help>Install New So ...
- ROS的launch文件
ROS中可以把很多的命令以描述的形式写成launch文件,然后用roslaunch命令执行launch文件.它的使用方法如下: roslaunch [package] [filename.launch ...
- python3 迭代器
''' 迭代:重复的过程,并且每次迭代的结果都是下次迭代的初始值 可迭代的 Iterable 迭代器 Iterator iter(数据) == 数据.__iter__() 将数据转换为迭代器 next ...