支持任意字段排序及多表关联查询的存储过程分页

 本文作者:草上飞
网址: www.newbooks.com.cn
QQ:1469886
如需转载,请保留以上信息。
谢谢!
点击下载支持多表关联任意字段排序的存储过程分页SQL>>>
网上有很多现成的存储过程分页sql,但是大多数只支持主键字段或者唯一值字段进行排序。而对于有重复值的字段进行排序的时候,数据会遗漏。 
而且很多存储过程分页脚本也不支持多表关联查询的分页,而我们现实应用中,一般都是多表关联的查询,针对这几个问题,我网上随便找了一个 
现成的脚本,进行了一下修改。修改后的脚本支持多表查询和任意字段排序(包括数值型字段)。 
以下脚本注释以我开发的新书城网上书店(www.newbooks.com.cn)为例进行注释。 
本存储过程分页的主要思路是,排序的同时引入主键字段,如果排序字段值重复的时候,来利用排序字段值相等,但是主键不相等的条件来取记录,具体以price字段升序排序为例进行讲解: 
1.先取得(@PageIndex-1)*@PageSize条记录中的price字段和主键字段。这些记录的顺序按照price升序和主键升序。 
相关sql伪代码为:select top (@PageIndex-1)*@PageSize tblbooks.price,tblbooks.bookid from tblbooks inner join tblbooktypes on tblbooks.bookid=tblbooktypes.bookid  
2.从上面的记录中取得top 1记录,top 1记录按照price降序和主键降序。其实就是取得上面记录中的最后一条记录,将这条记录的price字段和主键字段的值赋值给2个临时变量。 
相关sql伪代码为: 
select top 1 @orderFldValue=@orderFldName,@keyFldValue=@fldName from (select top (@PageIndex-1)*@PageSize tblbooks.price,tblbooks.bookid from tblbooks inner join tblbooktypes on tblbooks.bookid=tblbooktypes.bookid) 
3.我们取得上面2个值后,就可以把这2个值作为条件,来取得我们的分页数据了。思路就是top 20 ... where price>取出来的price or (price=取出来的price and 主键bookid>取出来的主键值) 
相关sql伪代码为: 
select top 20 @listFldName from @tblName where @strWhere and (price>@orderFldValue or (price=@orderFldValue and bookid>@keyFldValue)) 
从而我们取出了分页数据。 
调用的代码如下: 
exec GetRecordFromPage "tblbooks inner join tblbooktypes on tblbooks.bookid=tblbooktypes.bookid","tblbooks.bookid","tblbooks.bookid,tblbooks.bookname,tblbooks.price", 
"tblbooks.price","",20,3,0," tblbooktypes.typecode like '0.1.20%'" 
本存储过程sql语句如下:
/*  
  参数说明: @tblName     需要查询的表名。如图书表tblbooks  。如果是多表(图书表关联图书分类表)则写成:tblbooks inner join tblbooktypes on tblbooks.bookid=tblbooktypes.bookid   
           @fldName      主键字段名 bookid   
       @listFldName  需要查询的字段。如:书名(tblbooks.bookname)、作者(tblbooks.author)、价格(tblbooks.price)  
       @orderFldName 需要排序的字段。 如(tblbooks.price)  我们以非主键且有重复字段价格字段进行排序  
       @orderFldType 需要排序的字段的类型。   因为price这段类型为float,所以我们这里设置值为"float"。  
           @PageSize     每页记录数    
           @PageIndex    要获取的页码  
           @OrderType    排序类型, 0 - 升序, 1 - 降序  
           @strWhere     查询条件 (注意: 不要加 where)  
作者:草上飞  
Q Q:1469886  
说明:本存储过程为在优化新书城网上书店(www.newbooks.com.cn)的分页时候整理出来的。本存储过程可以任意转载,但在转载过程中请保留以上信息。谢谢!  
新书城网上书店(www.newbooks.com.cn)现有30几万的图书数量,利用该存储过程达到了根据价格、销量、出版日期等字段快速排序的效果,具体分页速度可进入该网站进行查看。  
如对该存储过程有疑问,请与本人联系。  
*/
  


CREATE     PROCEDURE  GetRecordFromPage  
    
@tblName        varchar ( 500 ),        
    
@fldName        varchar ( 50 ),         
    
@listFldName        varchar ( 255 ),         
    
@orderFldName        varchar ( 50 ),         
    
@orderFldType        varchar ( 50 ),         
    
@PageSize       int   =   10 ,             
    
@PageIndex      int   =   1 ,              
    
@OrderType      bit   =   0 ,              
    
@strWhere       varchar ( 2000 =   ''    
AS   

declare   @strSQL     nvarchar ( 4000 )        --  主语句  
declare   @strTmp     varchar ( 1000 )        --  临时变量  
declare   @strOrder   varchar ( 500 )         --  排序类型  
declare   @strOrder2   varchar ( 500 )        --    
declare   @orderFldValue   nvarchar ( 100 )   -- 排序字段对应的值    
declare   @keyFldValue   nvarchar ( 100 )   -- 主键字段对应的值 add  
declare   @operator   char ( 1 -- add by caoy  
declare   @tempValueSql   varchar ( 100 )  
declare   @strOrderby   varchar ( 5 )  
if  ( @orderFldType = ' float ' )  
    
set   @tempValueSql = ' cast(@orderFldValue as float) '   
else   
    
set   @tempValueSql = ' @orderFldValue '   

-- 获取表明 。  
declare   @tablename   varchar ( 20 )  
if   charindex ( ' . ' , @orderFldName ) > 1    
    
set   @tablename = left ( @orderFldName , charindex ( ' . ' , @orderFldName ) - 1 )  
else   
    
set   @tablename = @orderFldName   
if   @OrderType   !=   0     
begin   
    
set   @operator = ' < '   
    
set   @strOrderby = '  desc '   
    
set   @strOrder2 = '  asc '   
end   
else   
begin   
    
set   @operator = ' > '   
    
set   @strOrderby = '  asc '   
    
set   @strOrder2 = '  desc '   
end   
set   @strOrder = '  order by  ' +   @orderFldName + @strOrderby   
if   @fldName != @orderFldName    -- 如果排序字段不是主键字段,则增加主键排序  
     set   @strOrder = @strOrder + ' , ' + @fldName + @strOrderby   
-- 先得到orderFldValue和keyValue   
set   @strSQL = ' select top 1 @orderFldValue=convert(nvarchar(100), ' + @orderFldName + ' ,20) '    /***注意,如果需要排序的字段的值长度超过Nvarchar(100),请修改此处***********/   
if   @fldName != @orderFldName     
    
set   @strSQL = @strSQL + ' ,@keyFldValue= ' + @fldName   
else   
    
set   @strSQL = @strSQL + ' ,@keyFldValue=1 '   
set   @strSQL = @strSQL + '  from (select top  '   +   str (( @PageIndex - 1 ) * @PageSize +   '   '   
    
+   @orderFldName    
if   @fldName != @orderFldName    -- add by caoy  
     set   @strSQL = @strSQL + ' , ' + @fldName   
set   @strSQL = @strSQL +   '  from  '   +   @tblName   +   ''    
if   @strWhere   !=   ''   
    
set   @strSQL = @strSQL +   '  where  ' + @strWhere   
set   @strSQL = @strSQL +   @strOrder   +   ' ) as  ' + @tablename + '  order by  '   +   @orderFldName   + @strOrder2   
if   @fldName != @orderFldName    -- add by caoy  
     set   @strSQL = @strSQL + ' , '   +   @fldName   + @strOrder2   
-- print @strSQL  
exec    sp_executesql  @strSQL ,N ' @orderFldValue nvarchar(100) output,@keyFldValue nvarchar(100) output ' , @orderFldValue  output, @keyFldValue  output     /***注意,如果需要排序的字段的值长度超过Nvarchar(100),请修改此处***********/     
-- 得到排序字段值和主键值结束  



if   @PageIndex   =   1   
begin   
    
set   @strTmp   =   ''   
    
if   @strWhere   !=   ''   
        
set   @strTmp   =   '  where ( '   +   @strWhere   +   ' ) '   

    
set   @strSQL   =   ' select top  '   +   str ( @PageSize +   '   ' +   @listFldName + '  from  '   
        
+   @tblName   +   ''   +   @strTmp   +   '   '   +   @strOrder   
    
exec  ( @strSQL )  
end   
else   
begin    
    
-- 取得top数据并返回  
     set   @strSQL   =  N ' select top  '   +   str ( @PageSize + '   '   +    @listFldName + '  from  '   
        
+   @tblName   +   '  where ( ' + @orderFldName + @operator + @tempValueSql + '  and @keyFldValue=@keyFldValue '   
    
if   @fldName != @orderFldName    -- add by caoy  
         set   @strSQL = @strSQL +   '  or ( ' + @orderFldName + ' = ' + @tempValueSql + '  and  ' + @fldName + @operator + ' @keyFldValue)) and (1=1 '   
      
    
if   @strWhere   !=   ''   
        
set   @strSQL = @strSQL + '  and  '   +   @strWhere   
    
set   @strSQL = @strSQL +   ' ) ' + @strOrder   
        
if   @fldName = @orderFldName            
        
set   @keyFldValue = 1   
    
-- print @strSQL  
     exec  sp_executesql  @strSQL ,N ' @orderFldValue nvarchar(100),@keyFldValue nvarchar(100) ' , @orderFldValue , @keyFldValue   

      
end   

SET  QUOTED_IDENTIFIER  OFF   
GO  
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值