top
Loading...
關于存儲過程分頁
看了幾個朋友寫的關于存儲過程分頁的文章,感覺有點問題。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: bigeagle@163.net */
/* */
/* 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


北斗有巢氏 有巢氏北斗