深圳升蓝软件
数据库开发 .Net技术  |  ASP技术 PHP技术 JSP技术 应用技术类   
Hiblue Software

关于存储过程分页


March 25,2004
看了几个朋友写的关于存储过程分页的文章,感觉有点问题。starleee和东方蜘蛛希望我能发表点看法,我简单说一下。

    首先是allsky的那个分页方法根本就不成立,看看他是这样的:
select @iStart=(@iPage-1)*@iPageSize
select @iEnd=@iStart+@iPageSize+1
也就是说,他的开始和结束id按照每页显示数硬算出来的,想要这种方法成立必须满足这样一个条件,即这个论坛只有一个版面,并且id从1开始是连续的,中间不能有间隔,也就是说如果删贴了的话那就会出错。

    其次是starleee那个,其实思路是对的,但既然用求首尾id的方法分页,就没有必要用游标,可以利用select top *或set rowcount = 的语法来求出首尾id,第一种方法只能用在sql server里,而后一种在sybase和oracle里都能成立。
starleee提到说试验过这种方法不如用游标快,其实问题出在他的索引建的不好,没有专门为这个存储过程建立索引。影响数据库效率最大的因素就是索引,在这里有必要讲一下。理论上如果一个排序的第一个字段的索引不能过滤掉大部分数据,那么这个索引就是不恰当的,这样将可能有些晦涩,据个例子来说吧:
select id , name , forumid from tablexxx where forumid=1 and name like '%aaa%' order by id
看看上边这条语句,如果想要高效,就需要为它建立这样一个索引:
forumid , id
这样说把,如果在一个有百万条纪录的表中用这条语句,如果不建这个索引,最大的可能是要超时,而建立上述索引,如果有满足条件的纪录的话,那可以在1秒钟内响应(选出第一条符合条件的纪录),而如果没有满足条件的纪录,也可以在一分钟内响应。

下面这个存储过程是我的bbs利用求首尾id的方法分页的,大家可以看一下
/*************************************************************************/
/*                                                                       */
/*  procedure :       up_GetTopicList                                    */
/*                                                                       */
/*  Description:      贴子列表                                           */
/*                                                                       */
/*  Parameters:       @a_intForumID : 版面id                             */
/*                    @a_intPageNo:   页号                               */
/*                    @a_intPageSize: 每页显示数,以根贴为准             */
/*                                                                       */
/*  Use table:        bbs , forum                                        */
/*                                                                       */
/*  Author:           [email protected]                                   */
/*                                                                       */
/*  Date:             2000/2/14                                          */
/*                                                                       */
/*  History:                                                             */
/*                                                                       */
/*************************************************************************/
if exists(select * from sysobjects where id = object_id('up_GetTopicList'))
   drop proc up_GetTopicList
go

create proc up_GetTopicList
       @a_intForumID int ,
       @a_intPageNo int  ,
       @a_intPageSize int
as
   /*定义局部变量*/
   declare @intBeginID         int
   declare @intEndID           int
   declare @intRootRecordCount int
   declare @intPageCount       int
   declare @intRowCount        int
   /*关闭计数*/
   set nocount on
   
   /*检测是否有这个版面*/
   if not exists(select * from forum where id = @a_intForumID)
      return (-1)
  
   /*求总共根贴数*/
   select @intRootRecordCount = count(*) from bbs where fatherid=0 and forumid=@a_intForumID
   if (@intRootRecordCount = 0)    --如果没有贴子,则返回零
       return 0
      
   /*判断页数是否正确*/
   if (@a_intPageNo - 1) * @a_intPageSize > @intRootRecordCount
      return (-1)

   /*求开始rootID*/
   set @intRowCount = (@a_intPageNo - 1) * @a_intPageSize + 1
   /*限制条数*/
   set rowcount @intRowCount
   select @intBeginID = rootid from bbs where fatherid=0 and forumid=@a_intForumID
          order by id desc

   /*结束rootID*/
   set @intRowCount = @a_intPageNo * @a_intPageSize
   /*限制条数*/
   set rowcount @intRowCount
   select @intEndID = rootid from bbs where fatherid=0 and forumid=@a_intForumID
          order by id desc

   /*恢复系统变量*/
   set rowcount 0
   set nocount off   

   select a.id , a.layer , a.forumid , a.subject , a.faceid , a.hits , a.time , a.UserID , a.fatherid , a.rootid ,
         'Bytes' = datalength(a.content) , b.UserName , b.Email , b.HomePage , b.Signature , b.Point
     from bbs as a join BBSUser as b on a.UserID = b.ID
     where Forumid=@a_intForumID and a.rootid between @intEndID and @intBeginID
         order by a.rootid desc , a.ordernum desc
   return(@@rowcount)
   --select @@rowcount
go   

       
Copyright © 2001-2008 Shenzhen Hiblue Software Team All rights reserved