SQLServer 分页存储过程

SQLServer 分页存储过程

原作者:邹建(zjcxc)

来源:CSDN BLOG

原文地址:http://blog.csdn.net/zjcxc/archive/2003/12/29/20080.aspx

 

/*--用存储过程实现的分页程序

 显示指定表、视图、查询结果的第X页
 对于表中主键或标识列的情况,直接从原表取数查询,其它情况使用临时表的方法
 如果视图或查询结果中有主键,不推荐此方法

--邹建 2003.09(引用请保留此信息)--
*/


/*--调用示例
 exec p_show '地区资料'

 exec p_show '地区资料',5,3,'地区编号,地区名称,助记码','地区编号'
--
*/


if   exists  ( select   *   from  dbo.sysobjects  where  id  =   object_id (N ' [dbo].[p_show] ' and   OBJECTPROPERTY (id, N ' IsProcedure ' =   1 )
drop   procedure   [ dbo ] . [ p_show ]
GO

CREATE   Proc  p_show
@QueryStr   nvarchar ( 4000 ),  -- 表名、视图名、查询语句
@PageSize   int = 10 ,    -- 每页的大小(行数)
@PageCurrent   int = 1 ,    -- 要显示的页
@FdShow   nvarchar  ( 4000 ) = '' -- 要显示的字段列表,如果查询结果有标识字段,需要指定此值,且不包含标识字段
@FdOrder   nvarchar  ( 1000 ) = ''   -- 排序字段列表
as
declare   @FdName   nvarchar ( 250 -- 表中的主键或表、临时表中的标识列名
 , @Id1   varchar ( 20 ), @Id2   varchar ( 20 -- 开始和结束的记录号
 , @Obj_ID   int      -- 对象ID
--
表中有复合主键的处理
declare   @strfd   nvarchar ( 2000 -- 复合主键列表
 , @strjoin   nvarchar ( 4000 -- 连接字段
 , @strwhere   nvarchar ( 2000 -- 查询条件


select   @Obj_ID = object_id ( @QueryStr )
 ,
@FdShow = case   isnull ( @FdShow , '' when   ''   then   '  * '   else   '   ' + @FdShow   end
 ,
@FdOrder = case   isnull ( @FdOrder , '' when   ''   then   ''   else   '  order by  ' + @FdOrder   end
 ,
@QueryStr = case   when   @Obj_ID   is   not   null   then   '   ' + @QueryStr   else   '  ( ' + @QueryStr + ' ) a '   end

-- 如果显示第一页,可以直接用top来完成
if   @PageCurrent = 1  
begin
 
select   @Id1 = cast ( @PageSize   as   varchar ( 20 ))
 
exec ( ' select top  ' + @Id1 + @FdShow + '  from  ' + @QueryStr + @FdOrder )
 
return
end

-- 如果是表,则检查表中是否有标识更或主键
if   @Obj_ID   is   not   null   and   objectproperty ( @Obj_ID , ' IsTable ' ) = 1
begin
 
select   @Id1 = cast ( @PageSize   as   varchar ( 20 ))
  ,
@Id2 = cast (( @PageCurrent - 1 ) * @PageSize   as   varchar ( 20 ))

 
select   @FdName = name  from  syscolumns  where  id = @Obj_ID   and  status = 0x80
 
if   @@rowcount = 0     -- 如果表中无标识列,则检查表中是否有主键
  begin
  
if   not   exists ( select   1   from  sysobjects  where  parent_obj = @Obj_ID   and  xtype = ' PK ' )
   
goto  lbusetemp   -- 如果表中无主键,则用临时表处理

  
select   @FdName = name  from  syscolumns  where  id = @Obj_ID   and  colid  in (
   
select  colid  from  sysindexkeys  where   @Obj_ID = id  and  indid  in (
    
select  indid  from  sysindexes  where   @Obj_ID = id  and  name  in (
     
select  name  from  sysobjects  where  xtype = ' PK '   and  parent_obj = @Obj_ID
   )))
  
if   @@rowcount > 1    -- 检查表中的主键是否为复合主键
   begin
   
select   @strfd = '' , @strjoin = '' , @strwhere = ''
   
select   @strfd = @strfd + ' ,[ ' + name + ' ] '
    ,
@strjoin = @strjoin + '  and a.[ ' + name + ' ]=b.[ ' + name + ' ] '
    ,
@strwhere = @strwhere + '  and b.[ ' + name + ' ] is null '
    
from  syscolumns  where  id = @Obj_ID   and  colid  in (
    
select  colid  from  sysindexkeys  where   @Obj_ID = id  and  indid  in (
     
select  indid  from  sysindexes  where   @Obj_ID = id  and  name  in (
      
select  name  from  sysobjects  where  xtype = ' PK '   and  parent_obj = @Obj_ID
    )))
   
select   @strfd = substring ( @strfd , 2 , 2000 )
    ,
@strjoin = substring ( @strjoin , 5 , 4000 )
    ,
@strwhere = substring ( @strwhere , 5 , 4000 )
   
goto  lbusepk
  
end
 
end
end
else
 
goto  lbusetemp

/*--使用标识列或主键为单一字段的处理方法--*/
lbuseidentity: 
 
exec ( ' select top  ' + @Id1 + @FdShow + '  from  ' + @QueryStr
  
+ '  where  ' + @FdName + '  not in(select top  '
  
+ @Id2 + '   ' + @FdName + '  from  ' + @QueryStr + @FdOrder
  
+ ' ) ' + @FdOrder
  )
 
return

/*--表中有复合主键的处理方法--*/
lbusepk:  
 
exec ( ' select  ' + @FdShow + '  from(select top  ' + @Id1 + '  a.* from
  (select top 100 percent * from 
' + @QueryStr + @FdOrder + ' ) a
  left join (select top 
' + @Id2 + '   ' + @strfd + '  
  from 
' + @QueryStr + @FdOrder + ' ) b on  ' + @strjoin + '
  where 
' + @strwhere + ' ) a '
  )
 
return

/*--用临时表处理的方法--*/
lbusetemp:  
select   @FdName = ' [ID_ ' + cast ( newid ()  as   varchar ( 40 )) + ' ] '
 ,
@Id1 = cast ( @PageSize * ( @PageCurrent - 1 as   varchar ( 20 ))
 ,
@Id2 = cast ( @PageSize * @PageCurrent - 1   as   varchar ( 20 ))

exec ( ' select  ' + @FdName + ' =identity(int,0,1), ' + @FdShow + '
  into #tb from
' + @QueryStr + @FdOrder + '
 select 
' + @FdShow + '  from #tb where  ' + @FdName + '  between  '
 
+ @Id1 + '  and  ' + @Id2
 )

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值