目前来看较完美的通用二分法分页存储过程,not in模式,适用于非数值ID,可多字段排序,可以distinct——SQL Server...

/*
通用二分法分页存储过程,水稻并不是很懂存储过程,这段procedure起初也并非原创,但原版总是有些小问题,无奈之下水稻只好自己从头到尾把代码重写一遍,终于改出了一个比较完美的版本,此版本支持多表连接(要在调用前自己join好),支持distinct(我发现多数分页存储过程都不能完美的支持distinct),支持多字段排序(需要自行准备与原始排序完全相反的排序列表,否则取不到真实的记录),采用@ID not in模式,适用于不是以数值为主键的结构。
这里的大致思路就是取出不在前几页中的前@pagesize个记录,而之所以叫二分法,是对于后一半数据的处理是利用了反向排序来实现的,也就是利用反向排序使得处理后半部分记录时也只是处理一半的记录,这相显然会提高些效率。
这段代码据说效率还挺高,水稻没亲自测试过效率。
欢迎大家随便拿去用用,同时使用中如果发现什么问题欢迎随时反馈,水稻习惯在存储过程中进行分页处理,所以希望能写出更完美的分页存储过程来,也愿意把更完美的分页过程拿出与大家分享。
另外,也欢迎各路高人前来批评指教。
2009年9月1日完成的这一版经初步测试没有问题。
*/
CREATE   PROCEDURE  proc_pagination
(
@tblName   nvarchar ( 1000 ),         -- --要显示的表或多个表的连接,必须参数
@fldName    nvarchar ( 4000 =   ' * ' ,     -- --要显示的字段列表
@fldSort    nvarchar ( 4000 =   null ,     -- --排序字段列表或条件
@fldFSort   nvarchar ( 4000 =   null ,     -- --反向排序字段列表或条件(这个需要在调用前准备好,且一定要与原始排序完全相反)
@strCondition    nvarchar ( 4000 =   null ,     -- --查询条件,不需where
@ID   nvarchar ( 1000 ),         -- --主表的主键,必须参数
@Dist   bit   =   0 ,            -- --是否添加查询字段的 DISTINCT 默认0不添加/1添加
@pageSize   int   =   10 ,         -- --每页显示的记录个数
@currentpage   int   =   1 ,         -- --要显示那一页的记录
@pageCount   int   =   1  output,             -- --查询结果分页后的总页数
@Counts   int   =   1  output                 -- --查询到的记录数
)
AS
SET  NOCOUNT  ON
Declare   @sqlTmp   nvarchar ( 4000 )         -- --存放动态生成的SQL语句
Declare   @strTmp   nvarchar ( 4000 )         -- --存放取得查询结果总数的查询语句
Declare   @strID   nvarchar ( 1000 )         -- --存放取得查询开头或结尾ID的查询语句

Declare   @strSort   nvarchar ( 4000 )     -- --数据排序规则A
Declare   @strFSort   nvarchar ( 4000 )     -- --数据排序规则B

Declare   @SqlSelect   nvarchar ( 50 )          -- --对含有DISTINCT的查询进行SQL构造
Declare   @SqlCounts   nvarchar ( 50 )           -- --对含有DISTINCT的总数查询进行SQL构造

Declare   @IDSords   nvarchar ( 4000 )         -- --ID和所有参加排序的字段,用于distinct和order by

if   @Dist    =   0      -- 不带distinct
begin
    
set   @SqlSelect   =   ' select  '
    
set   @SqlCounts   =   ' Count(1) '
end
else
begin
    
set   @SqlSelect   =   ' select distinct  '
    
set   @SqlCounts   =   ' Count(DISTINCT  ' + @ID + ' ) '
end

-- 本来应该在这里分析@fldSort,然后自动生成反向排序字段
set   @strSort = @fldSort
set   @strFSort = @fldFSort

-- ------生成查询语句--------
--
此处@strTmp为取得查询结果数量的语句
if   @strCondition   is   null   or   @strCondition = ''       -- 没有查询条件,不带where
begin
    
set   @sqlTmp   =    @fldName   +   '  From  '   +   @tblName
    
set   @strTmp   =   @SqlSelect + '  @Counts= ' + @SqlCounts + '  FROM  ' + @tblName
    
set   @strID   =   '  From  '   +   @tblName
end
else
begin
    
set   @sqlTmp   =   +   @fldName   +   '  From  '   +   @tblName   +   '  where  '   +   @strCondition
    
set   @strTmp   =   @SqlSelect + '  @Counts= ' + @SqlCounts + '  FROM  ' + @tblName   +   '  where  '   +   @strCondition
    
set   @strID   =   '  From  '   +   @tblName   +   '  where  '   +   @strCondition
end


-- --取得查询结果总数量-----
exec  sp_executesql  @strTmp ,N ' @Counts int out  ' , @Counts  out

declare   @tmpCounts   int
if   @Counts   =   0
    
set   @tmpCounts   =   1
else
    
set   @tmpCounts   =   @Counts

    
-- 取得分页总数
     set   @pageCount = ( @tmpCounts + @pageSize - 1 ) / @pageSize

    
/**//* *当前页大于总页数 取最后一页* */
    
if   @currentpage > @pageCount
        
set   @currentpage = @pageCount

    
-- /*-----数据分页2分处理-------*/
     declare   @pageIndex   int   -- 总数/页大小
     declare   @lastcount   int   -- 总数%页大小 

    
set   @pageIndex   =   @tmpCounts / @pageSize
    
set   @lastcount   =   @tmpCounts % @pageSize
    
if   @lastcount   >   0
        
set   @pageIndex   =   @pageIndex   +   1      -- --@lastcount>0说明最后一页还有记录,所以就应该再多一页
     else
        
set   @lastcount   =   @pageSize

    
-- //***显示分页
     if   @strCondition   is   null   or   @strCondition = ''       -- 没有查询条件where
         begin
            
if   @pageIndex < 2   or   @currentpage <= @pageIndex   /   2   +   @pageIndex   %   2     -- 前半部分数据处理
                 begin  
                    
if   @fldSort   is   null   or   @fldSort = ''      -- 没有排序
                         set   @strTmp = @SqlSelect + '  top  ' +   CAST ( @pageSize   as   VARCHAR ( 4 )) + '   ' +   @fldName + '  from  ' + @tblName
                                
+ '  where  ' + @ID + '  not in(select  ' + @ID + '  from  '
                                
+ ' ( ' +   @SqlSelect + '  top  ' +   CAST ( @pageSize * ( @currentpage - 1 as   Varchar ( 20 ))
                                
+ '   ' +   @fldName   + '  from  ' + @tblName   + ' ) as TempTBL) '
                        
-- 取的是id不在前(@currentpage-1)页中,即不是前(@currentpage-1)*@pagesize条记录的前@pagesize条记录
                     else      -- 如果有排序的话
                         set   @strTmp = @SqlSelect + '  top  ' +   CAST ( @pageSize   as   VARCHAR ( 4 )) + '   ' +   @fldName + '  from  ' + @tblName
                                
+ '  where  ' + @ID + '  not in(select  ' + @ID + '  from ( '
                                
+   @SqlSelect + '  top  ' +   CAST ( @pageSize * ( @currentpage - 1 as   Varchar ( 20 ))  + '   ' +   @fldName
                                
+ '  from  ' + @tblName
                                
+ '  order by  ' +   @strSort + ' ) as TempTBL) '
                                
+ '  order by  ' +   @strSort  
                        
-- 按正序排序取前(@currentpage-1)*@pagesize条记录,然后再按正序排序把前(@currentpage-1)*@pagesize条记录排除取前@pagesize条记录
                 end
            
else                                   -- 后半部分数据处理
                 begin
                
set   @currentpage   =   @pageIndex - @currentpage + 1
                    
if   @currentpage   <=   1   -- 最后一页数据显示
                         if   @fldSort   is   null   or   @fldSort = ''      -- 没有排序
                             set   @strTmp = @SqlSelect + '   ' + @fldName + '  from ( '
                                
+   @SqlSelect   + '   '   +   @fldName +   '  from  ' + @tblName
                                
+ '  where  ' + @ID   +   '  not in (select  ' + @ID + '  from( '
                                
+ @SqlSelect + '  top  ' + CAST ( @pageSize * ( @pageIndex - 1 as   VARCHAR ( 4 )) + '   ' + @fldName
                                
+ '  from  ' + @tblName
                                
+ ' ) as TempTBL)) AS TempTB '
                                
-- 如果是最后一页就没必要再用top了,直接把不在前@pagesize*(@pageindex-1)页中的记录取出就可以
                         else      -- 如果有排序的话
                             set   @strTmp = @SqlSelect + '   ' + @fldName + '  from ( '
                                
+ @SqlSelect + '  top  ' +   CAST ( @lastcount   as   VARCHAR ( 4 )) + '   ' +   @fldName
                                
+ '  from  ' + @tblName
                                
+ '  order by  ' +   @strFSort   + ' ) AS TempTB ' + '  order by  ' +   @strSort
                                
-- 先反向排序,取出前@lastcount条记录,再进行正向排序
                     else      -- 不是最后一页,即后半部分的其他页
                         if   @fldSort   is   null   or   @fldSort = ''      -- 没有排序时
                             set   @strTmp = @SqlSelect + '  top  ' +   CAST ( @pageSize   as   VARCHAR ( 4 )) + '   ' +   @fldName + '  from  ' + @tblName
                                    
+ '  where  ' + @ID + '  not in(select  ' + @ID + '  from( '
                                    
+   @SqlSelect + '  top  ' +   CAST ( @pageSize * ( @currentpage - 1 as   Varchar ( 20 ))
                                    
+ '   ' +   @fldName   + '  from  ' + @tblName   + ' ) as TempTBL) '
                                    
-- 不排序时跟前半部分应该一样处理
                         /*
                            set @strTmp=@SqlSelect+' '+@fldName+' from ('
                                +@SqlSelect+' top '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName
                                +' from '+@tblName +' where '+@ID+' not in('
                                + @SqlSelect+' top '+ CAST(@pageSize*(@currentpage-2)+@lastcount as Varchar(20)) +' '+ @fldName
                                 +' from '+@tblName +')'
                                +') AS TempTB' 
                                
*/
                        
else          -- 有排序时   
                             set   @strTmp = @SqlSelect + '   ' + @fldName + '  from ( '
                                
+ @SqlSelect + '  top  ' +   CAST ( @pageSize   as   VARCHAR ( 4 )) + '   ' +   @fldName
                                
+ '  from  ' + @tblName   + '  where  ' + @ID + '  not in(select  ' + @ID + '  from( '
                                
+   @SqlSelect + '  top  ' +   CAST ( @pageSize * ( @currentpage - 2 ) + @lastcount   as   Varchar ( 20 ))  + '   ' +   @fldName
                                
+ '  from  ' + @tblName   + '  order by  ' +   @strFSort   + ' ) as TempTBL) '
                                
+ '  order by  ' +   @strFSort   + ' ) AS TempTB '
                                
+ '  order by  ' +   @strSort
                                
-- 先反向排序取出前(@currentpage-1)页的记录(其中包括不满一整页的最后一页,所以是前@pagesize*(@currentpage-2)+@lastcount条记录)
                                 -- 然后仍然反向排序,这回取不在上一结果集里的前@pagesize条记录,即该得到的记录
                                 -- 最后进行一次正向排序
                 end
        
end
    
else   -- 有查询条件
         begin
            
if   @pageIndex < 2   or   @currentpage <= @pageIndex   /   2   +   @pageIndex   %   2     -- 前半部分数据处理
                 begin
                    
if   @fldSort   is   null   or   @fldSort = ''      -- 没有排序
                         set   @strTmp = @SqlSelect + '  top  ' +   CAST ( @pageSize   as   VARCHAR ( 4 )) + '   ' +   @fldName   + '  from   ' + @tblName
                            
+ '  where  ' + @ID + '  not in(select  ' + @ID + '  from( '
                            
+   @SqlSelect + '  top  ' +   CAST ( @pageSize * ( @currentpage - 1 as   Varchar ( 20 ))  + '   ' +   @fldName
                            
+ '  from  ' + @tblName
                            
+ '  Where  '   +   @strCondition   +   ' ) as TempTBL) '
                            
+ '  and  '   +   @strCondition
                            
-- 先取出带where后的前@pagesize*(@currentpage-1)条记录
                             -- 再取出不在这@pagesize*(@currentpage-1)条记录中的还where的前@pagesize条记录
                     else          -- 有排序
                         set   @strTmp = @SqlSelect + '  top  ' +   CAST ( @pageSize   as   VARCHAR ( 4 )) + '   ' +   @fldName   + '  from   ' + @tblName
                            
+ '  where  ' + @ID + '  not in(select  ' + @ID + '  from( '
                            
+   @SqlSelect + '  top  ' +   CAST ( @pageSize * ( @currentpage - 1 as   Varchar ( 20 ))  + '   ' +   @fldName
                            
+ '  from  ' + @tblName   + '  Where  '   +   @strCondition   +   '  order by  ' +   @strSort   + ' ) as TempTBL) '
                            
+ '  and  '   +   @strCondition   +   '  order by  ' +   @strSort
                            
-- 1、正向排序,取出带where后的前@pagesize*(@currentpage-1)条记录
                             -- 2、正向排序,取出不在这@pagesize*(@currentpage-1)条记录中的还where的前@pagesize条记录
                 end
            
else      -- 后半部分
                 begin  
                    
set   @currentpage   =   @pageIndex - @currentpage + 1   -- 后半部分数据处理
                     if   @currentpage   <=   1   -- 最后一页数据显示
                         if   @fldSort   is   null   or   @fldSort = ''
                            
set   @strTmp = @SqlSelect + '   ' + @fldName   +   '  from  ' + @tblName
                                
+ '  where  ' + @ID   +   '  not in (select  ' + @ID + '  from( '
                                
+ @SqlSelect + '  top  ' + CAST ( @pagesize * ( @pageIndex - 1 as   VARCHAR ( 4 )) + '   ' + @fldName
                                
+ '  from  ' + @tblName   + '  where  ' + @strCondition
                                
+ ' ) as TempTBL) and  ' + @strCondition
                            
-- 取不在前@pageIndex-1页中的记录
                         else      -- 有排序,即既有条件又有排序
                             set   @strTmp = @SqlSelect + '   ' + @fldName + '  from ( '
                                
+ @SqlSelect + '  top  ' +   CAST ( @lastcount   as   VARCHAR ( 4 )) + '   ' +   @fldName
                                
+ '  from  ' + @tblName + '  where  ' +   @strCondition
                                
+ '  order by  ' +   @strFSort   + ' ) AS TempTB ' + '  order by  ' +   @strSort
                            
-- 先倒序排列,取前@lastcount条记录
                             -- 再正序排序
                     else      -- 后半部分,但不是最后一页
                         if   @fldSort   is   null   or   @fldSort = ''      -- 没有排序条件
                             set   @strTmp = @SqlSelect + '  top  ' +   CAST ( @pageSize   as   VARCHAR ( 4 )) + '   ' +   @fldName   + '  from   ' + @tblName
                                
+ '  where  ' + @ID + '  not in(select  ' + @ID + '  from( '
                                
+   @SqlSelect + '  top  ' +   CAST ( @pageSize * ( @currentpage - 1 as   Varchar ( 20 ))  + '   ' +   @fldName
                                
+ '  from  ' + @tblName
                                
+ '  Where  '   +   @strCondition   +   ' ) as TempTBL) '
                                
+ '  and  '   +   @strCondition
                                
-- 不排序时应该与前半部分相同处理
                         else      -- 有排序字段、有查询条件、后半部分非最末页
                             set   @strTmp = @SqlSelect + '   ' + @fldName + '  from ( '
                                
+ @SqlSelect + '  top  ' +   CAST ( @pageSize   as   VARCHAR ( 4 )) + '   ' +   @fldName
                                
+ '  from  ' + @tblName   + '  where  ' + @ID + '  not in ( '
                                
+ ' select  ' + @ID + '  from ( '
                                
+   @SqlSelect + '  top  ' +   CAST ( @pageSize * ( @currentpage - 2 ) + @lastcount   as   Varchar ( 20 ))  + '   ' +   @fldName
                                
+ '  from  ' + @tblName   + '  where  ' +   @strCondition   + '  order by  ' +   @strFSort   + ' ) as TempTBL) '
                                
+ '  and  '   +   @strCondition   + '  order by  ' +   @fldFSort   + ' ) AS TempTB ' + '  order by  ' +   @strSort
                
end     
        
end

-- ----返回查询结果-----
exec  sp_executesql  @strTmp
-- print @strTmp
SET  NOCOUNT  OFF

 

转载于:https://www.cnblogs.com/chenqiang001/archive/2009/09/01/1558077.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值