分页SQL语句/存储过程(.net/SQL技术交流群206656202 入群需注明博客园)
这里我用一表来举例 表名为 AddressSheng,主键ID自动增长,AddressName是省的名称
1、select ID,AddressName from (select *,Row_Number() over(order by ID DESC)RowNumber from AddressSheng)t where t.RowNumber>=((pageNumber-1)*pageSize+1) and t.RowNumber<=pageNumber*pageSize
pageNumber是查第几页的数据,第几页是从1开始的而不是0 因此我命名为pageNumber而不是pageIndex
pageSize是页容量,意思是每页显示多少条数据,其他的不必说了吧,记住一个公式就可以了
n为页码 s为页容量
t.RowNumber>=(n-1)*s+1 and t.RowNumber<=n*s
OK现在我们把它变成存储过程
create proc GetPageContentByPageNumber
(
@pageNumber int, --输入参数页码
@pageSize int, --页容量
@rowCount int output, --输出参数数据总数
@pageCount int output --输出参数总页数
)
as
Begin
declare @sql nvarchar(512)
select @rowCount=count(id),@pageCount=ceiling((count(id)+0.00)/@pageSize) from AddressSheng
set @sql ='select ID,AddressName from (select *,Row_Number() over(order by ID DESC)RowNumber from AddressSheng)t where t.RowNumber>='+str((@pageNumber-1)*@pageSize+1)+' and t.RowNumber<='+str(@pageNumber*@pageSize)
print @sql
exec (@sql)
End
--------------------------------------以下是调用存储过程-----------------------------------------------------
declare @pageNumber int,@pageSize int,@rowCount int,@pageCount int
exec GetPageContentByPageNumber
2, --请求第2页的数据
3, --页容量为3
@rowCount output, --数据总量
@pageCount output --总页数
这就是个分页请求数据的存储过程,我得说说原理,主要用的是Row_Number()这个函数来实现的分页,这个函数是Ms-SqlServer2000之后才有的,使用Row_Numer()函数会生成一列连续的自动增长的编号,由于我们差分页数据的时候,比如主键是自动增长列,那么主键就有可能是不连续的,所以我们用Row_Number()为它生成一个连续的序列号。ceiling(m)函数,我喜欢把它通俗的称作天花板函数,顾名思义就是往上取值,究竟是取得什么值呢?取不小于m的最大整数,举个例子 ceiling(1)=1;ceiling(1.1)=2;ceiling(1.7)=2 这么举例是不是更容易理解呢?在这里需要注意的是设置为黄色背景的括号一定不能省略否则结果是错误的,OK 这种方法的分页就说到这里.
2、
select top pageSize from AddressSheng where ID not in (select top (pageNumber-1)*pageSize ID from AddressSheng)
pageNumber依然是页码号,pageSize依然是页容量,这里又一个公式我用黄色背景做标注。
下面是存储过程
create proc GetPageContentByPageNumber
(
@pageNumber int,
@pageSize int,
@rowCount int output,
@pageCount int output
)
as
Begin
declare @sql nvarchar(512)
select @rowCount=count(id),@pageCount=ceiling((count(id)+0.00)/@pageSize) from AddressSheng
set @sql='select top '+str(@pageSize)+' * from AddressSheng where id not in (select top '+str((@pageNumber-1)*@pageSize)+' id from AddressSheng)'
print @sql
exec(@sql)
End
declare @pageNumber int,@pageSize int,@rowCount int,@pageCount int
exec t
2,
3,
@rowCount output,
@pageCount output
这种分页方式主要是用not in关键字来实现的,具体说一下比如我们要查询页码2的数据页容量为3,先计算出第一页的ID,然后在查询3条数据(pageSize),这时就有一个条件了是要查询出的数据的ID不包含刚刚查询出来的ID中,这样自然而然查询到的就是第2页的数据,str()函数是把括号的内容转换成字符串。简单吗?呵呵?
3、
select top 3 from AddressShent where ID>(select max(ID) from (select top (pageNumber-1)*pageSize ID from AddressSheng) as t)
存储过程:
create proc tt
(
@pageNumber int,
@pageSize int,
@rowCount int output,
@pageCount int output
)
as
Begin
declare @sql nvarchar(512)
select @rowCount=count(id),@pageCount=ceiling((count(id)+0.00)/@pageSize) from AddressSheng
set @sql='select top '+str(@pageSize)+' * from AddressSheng where ID>(select max(id) from (select top '+str((@pageNumber-1)*@pageSize)+' from AddressSheng) as t)'
print @sql
exec(@sql)
End
declare @pageNumber int,@pageSize int,@rowCount int,@pageCount int
exec t
2,
3,
@rowCount output,
@pageCount output
还是说说这种方法的原理,这里用到了一个函数max() 得到该列的最大值,比如max(ID)意思就是得到最大的ID号.
这种分页的方式也较为简单,我剖析下原理,拿到请求的页码以及页容量,页码-1就是上一页的数据,查出请求页上一页的数据然后得到它的最大的ID号,然后再从表中查若干条数据(pageSize)过滤条件是这些数据的ID大于刚刚查询出的最大ID号,这样我们不就实现了吗?是不是还挺简单?
总结:每种方式都各有优缺点,简单的说一下,第三种方式只能用在主键为自动增长列的表中,因为他要得到最大的ID号,如果是表主键是时间戳类型他就不灵了,第一种和第二种则没有这个缺陷。在从效率上来讲第一种是比第二种和第一种的效率高,然后第三种比第二种效率高。具体使用哪种是不是也分析出来了呢?时间太晚了今天就不比较效率了,在我的下一篇博客中我会用具体的方式测试下着三种分页的方式,咱在深入一步。郑重声明本人也是菜鸟,如果说的不正确的情况欢迎探讨莫要谩骂哦,欢迎经常来访。