/*------------------------------------------------------------
--
--通用分页存储过程(二分法+临时表修正排序)
[email protected]
--
-------------------------------------------------------------*/
CREATE PROCEDURE [Pr_PageList_finnal]
(
@tblName     nvarchar(200),        ----要显示的表或多个表的连接
@fldName     nvarchar(500) = '*',  ----要显示的字段列表
@pageSize    int = 10,            ----每页显示的记录个数
@page        int = 10,             ----要显示那一页的记录
@sortRule varchar(1000),  ---排序约束 类似  a.xx desc,b.xx as
@sortRuleReverse varchar(1000), ---排序约束 与上一条件相反即可如 a.xx asc,b.xx desc
@filter      nvarchar(1000) = null,----查询条件,不需where
@primaryKey  nvarchar(150),        ----主表的主键 必须为自增量 也就是说 此列不存在任何重复值
@pageCount   int = 1 output,       ----查询结果分页后的总页数
@totalRecord int = 1 output,       ----查询到的记录数
@returnSql   nvarchar(1000) = '' output  -----最后返回的SQL语句
)
AS
SET NOCOUNT ON ---不返回计数(表示受 Transact-SQL 语句影响的行数)
Declare @sqlTmp  nvarchar(1000)     ----存放动态生成的SQL语句
Declare @strTmp  nvarchar(1000)     ----存放取得查询结果总数的查询语句
Declare @strID      nvarchar(1000)     ----存放取得查询开头或结尾ID的查询语句
/*
Declare @sortTypeA  nvarchar(10)       ----数据排序规则A
Declare @sortTypeB  nvarchar(10)       ----数据排序规则B
*/
Declare @sqlSelect  nvarchar(50)   
Declare @sqlCounts  nvarchar(50)      
Declare @Erro                 nvarchar(500)    -----错误统计if  @primaryKey=''
     begin
           set @Erro='没有传入主键'
           return @Erro;
           return
     end--------生成查询语句--------
--此处@strTmp为取得查询结果数量的语句
set @sqlSelect='select '
set @sqlCounts=' count(1) '
if @filter is null or @filter=''     --没有设置显示条件
begin
set @sqlTmp =  @fldName + ' FROM ' + @tblName
set @strTmp = @sqlSelect+' @totalRecord='+@sqlCounts+' FROM '+@tblName
set @strID = ' FROM ' + @tblName
end
else
begin
set @sqlTmp =  @fldName + 'FROM ' + @tblName + ' WHERE ' + @filter
set @strTmp = @sqlSelect+' @totalRecord='+@sqlCounts+' FROM '+@tblName + ' WHERE ' + @filter
set @strID = ' FROM ' + @tblName + ' WHERE ' + @filter
end
----取得查询结果总数量-----
exec sp_executesql @strTmp,N'@totalRecord int out ',@totalRecord out
/* 记录总数获取完毕*/ /*取得分页总数*/
declare @tmpCounts int
if @totalRecord = 0
    set @tmpCounts = 1
else
    set @tmpCounts = @totalRecord
    set @pageCount=(@tmpCounts+@pageSize-1)/@pageSize--数据页总数
    
 /*当前页大于总页数 取最后一页*/
    if @page>@pageCount
        set @page=@pageCount
    
/*-----数据分页2分处理-------*/
    declare @pageIndex int --总数/页大小
    declare @lastcount int --总数%页大小 
    set @pageIndex = @tmpCounts/@pageSize
    set @lastcount = @tmpCounts%@pageSize
    if @lastcount > 0
        set @pageIndex = @pageIndex + 1
    else
        set @lastcount = @pagesize     
  /*-----------显示分页-------------*/
    if @filter is null or @filter=''     --没有设置显示条件
    begin
        if @pageIndex<2 or @page<=@pageIndex / 2 + @pageIndex % 2   --前半部分数据处理
            begin
                set @strTmp=@sqlSelect+' TOP '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName+' FROM '+@tblName
                    +' WHERE '+@primaryKey+' NOT IN('+ @sqlSelect+' TOP '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @primaryKey +' FROM '+@tblName
                    +' ORDER BY '+ @sortRule+')'
                    +' ORDER BY '+@sortRule
            end
        else
            begin
            set @page = @pageIndex-@page+1    ------------------------后半部分数据处理
                if @page <= 1 --最后一页数据显示
                   begin
                      set @strTmp='create Table  #TempTable(PagingId int identity(1,1),maidId int) '
                      set @strTmp=@strTmp+'  insert into #TempTable(maidId) '+ @sqlSelect+' TOP '+ CAST(@lastcount as VARCHAR(4))+' '+ @primaryKey+ '  FROM '+@tblName
                        +' ORDER BY '+ @sortRuleReverse
                      set @strTmp=@strTmp+' select '+@fldName+' '+' from '+ @tblName +' ,#TempTable where #TempTable.maidId='+@primaryKey+' and '+@filter+' order by PagingId desc'
                      set @strTmp=@strTmp+' drop table #TempTable'
                   end
                else   
                   begin   
                     set @strTmp='create Table  #TempTable(PagingId int identity(1,1),maidId int) '          
                     set @strTmp=@strTmp+'  insert into #TempTable(maidId) '+@sqlSelect+' TOP '+ CAST(@pageSize as VARCHAR(4))+' '+ @primaryKey+' FROM '+@primaryKey
                        +' WHERE '+@primaryKey+' not in('+ @sqlSelect+' TOP '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @primaryKey +' from '+@tblName
                        +' ORDER BY '+ @sortRuleReverse+')'
                        +' ORDER BY '+ @sortRuleReverse
                    set @strTmp=@strTmp+' select '+@fldName+' '+' from '+ @tblName +' ,#TempTable where #TempTable.maidId='+@primaryKey+' and '+@filter+' order by PagingId desc'
                     set @strTmp=@strTmp+' drop table #TempTable'
                 end
            end
    end
    else --有查询条件
    begin
        if @pageIndex<2 or @page<=@pageIndex / 2 + @pageIndex % 2   --前半部分数据处理
        begin
             set @strTmp=@sqlSelect+' TOP '+ CAST(@pageSize as VARCHAR(4))+' '+ @fldName +' FROM '+@tblName
         +' WHERE '+@primaryKey+' NOT IN('+ @sqlSelect+' top '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @primaryKey +' FROM '+@tblName
         +' Where  ' + @filter + ' ORDER BY '+@sortRule+') '
         +' AND ' + @filter + ' ORDER BY '+ @sortRule
        end
        else
        begin 
            set @page = @pageIndex-@page+1 --后半部分数据处理
            if @page <= 1 --最后一页数据显示
                begin
                    set @strTmp='create Table  #TempTable(PagingId int identity(1,1),maidId int) '       
                    set @strTmp=@strTmp+'insert into #TempTable(maidId) '+@sqlSelect+' TOP '+ CAST(@lastcount as VARCHAR(4))+' '+ @primaryKey+' FROM '+@tblName
                        +' WHERE '+ @filter +' ORDER BY '+ @sortRuleReverse
                    set @strTmp=@strTmp+' select '+@fldName+' '+' from '+ @tblName +' ,#TempTable where #TempTable.maidId='+@primaryKey+' and '+@filter+' order by PagingId desc'
                    set @strTmp=@strTmp+' drop table #TempTable'
                end
            else
               begin
                     set @strTmp='create Table  #TempTable(PagingId int identity(1,1),maidId int) '               
                     set @strTmp=@strTmp+'insert into #TempTable(maidId) '+@sqlSelect+' TOP '+ CAST(@pageSize as VARCHAR(4))+' '+ @primaryKey+' FROM '+@tblName
                        +' WHERE '+@primaryKey+' not in('+ @sqlSelect+' TOP '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @primaryKey +' FROM '+@tblName
                        +' WHERE '+ @filter +' ORDER BY '+@sortRuleReverse+') '
                        +' AND '+ @filter +' ORDER BY '+ @sortRuleReverse
                   set @strTmp=@strTmp+' select '+@fldName+' '+' from '+ @tblName +' ,#TempTable where #TempTable.maidId='+@primaryKey+' and '+@filter+' order by PagingId desc'
                    set @strTmp=@strTmp+' drop table #TempTable'
              end
        end    
    end
------返回查询结果-----
set @returnSql = @strTmp
exec sp_executesql @strTmp
SET NOCOUNT OFF
GO

解决方案 »

  1.   

    Declare @sqlTmp     nvarchar(1000)     ----存放动态生成的SQL语句
    Declare @strTmp     nvarchar(1000)     ----存放取得查询结果总数的查询语句
    Declare @strID         nvarchar(1000)     ----存放取得查询开头或结尾ID的查询语句
    放sql语句1000很可能不够,放4000或者max(2005或以上版本才支持)
      

  2.   

    其实通用性不够
    @primaryKey  nvarchar(150),        ----主表的主键 必须为自增量 也就是说 此列不存在任何重复值
    这里就限制了很多,只能是单字段整型的主键
    写得有点太长了,看起来累看看邹建blog上的分页存储过程可能对你有帮助
      

  3.   

    Create procedure [dbo].[uspCustomPaging] 
        @TableName varchar(50),                  --表或视图名
        @Fields varchar(5000) = '*',              --字段名(全部字段为*)
        @OrderFields varchar(5000),            --排序字段(必须!支持多字段,建议建索引)
        @SqlWhere varchar(5000) = '',         --条件语句(如and Name='a')
        @PageSize int,                                     --每页多少条记录
        @PageIndex int = 1 ,                           --指定当前为第几页
        @TotalPages int output                    --返回总页数 
    as
    begin
        declare @sql nvarchar(4000)
        declare @TotalRecords int       --计算总记录数及总页数     
        set @sql = 'select @TotalRecords = count(*) from ' + @TableName + ' where 1=1 ' + @sqlWhere
        exec sp_executesql @sql,N'@totalRecords int output',@TotalRecords output
        select @TotalPages=CEILING((@TotalRecords+0.0)/@PageSize)    --处理页数超出范围情况
        if @PageIndex<=0 
            set @PageIndex = 1
        if @PageIndex>@TotalPages
            set @PageIndex = @TotalPages    set @sql = 'select '+ @Fields + ' from (select top(@PageIndex*@PageSize) ' + @Fields + ',row_number() over(order by ' + @OrderFields + ') as rowNumber from ' + @TableName + ' where 1=1 ' + @SqlWhere + ') t where t.rowNumber >= ((@PageIndex-1)*@PageSize+1)'
        
        --print @Sql   
        exec sp_executesql @sql,N'@PageIndex int, @PageSize int',@PageIndex,@PageSize  
    end是不是这意思