看了幾個朋友寫的關(guān)于存儲過程分頁的文章,感覺有點問題。starleee和東方蜘蛛希望我能發(fā)表點看法,我簡單說一下。
首先是allsky的那個分頁方法根本就不成立,看看他是這樣的: select @iStart=(@iPage-1)*@iPageSize select @iEnd=@iStart+@iPageSize+1 也就是說,他的開始和結(jié)束id按照每頁顯示數(shù)硬算出來的,想要這種方法成立必須滿足這樣一個條件,即這個論壇只有一個版面,并且id從1開始是連續(xù)的,中間不能有間隔,也就是說如果刪貼了的話那就會出錯。
其次是starleee那個,其實思路是對的,但既然用求首尾id的方法分頁,就沒有必要用游標,可以利用select top *或set rowcount = 的語法來求出首尾id,第一種方法只能用在sql server里,而后一種在sybase和oracle里都能成立。 starleee提到說試驗過這種方法不如用游標快,其實問題出在他的索引建的不好,沒有專門為這個存儲過程建立索引。影響數(shù)據(jù)庫效率最大的因素就是索引,在這里有必要講一下。理論上如果一個排序的第一個字段的索引不能過濾掉大部分數(shù)據(jù),那么這個索引就是不恰當?shù)模@樣將可能有些晦澀,據(jù)個例子來說吧: select id , name , forumid from tablexxx where forumid=1 and name like '%aaa%' order by id 看看上邊這條語句,如果想要高效,就需要為它建立這樣一個索引: forumid , id 這樣說把,如果在一個有百萬條紀錄的表中用這條語句,如果不建這個索引,最大的可能是要超時,而建立上述索引,如果有滿足條件的紀錄的話,那可以在1秒鐘內(nèi)響應(選出第一條符合條件的紀錄),而如果沒有滿足條件的紀錄,也可以在一分鐘內(nèi)響應。
下面這個存儲過程是我的bbs利用求首尾id的方法分頁的,大家可以看一下 /*************************************************************************/ /* */ /* procedure : up_GetTopicList */ /* */ /* Description: 貼子列表 */ /* */ /* Parameters: @a_intForumID : 版面id */ /* @a_intPageNo: 頁號 */ /* @a_intPageSize: 每頁顯示數(shù),以根貼為準 */ /* */ /* 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 /*關(guān)閉計數(shù)*/ set nocount on
/*檢測是否有這個版面*/ if not exists(select * from forum where id = @a_intForumID) return (-1)
/*求總共根貼數(shù)*/ select @intRootRecordCount = count(*) from bbs where fatherid=0 and forumid=@a_intForumID if (@intRootRecordCount = 0) --如果沒有貼子,則返回零 return 0
/*判斷頁數(shù)是否正確*/ if (@a_intPageNo - 1) * @a_intPageSize > @intRootRecordCount return (-1)
/*求開始rootID*/ set @intRowCount = (@a_intPageNo - 1) * @a_intPageSize + 1 /*限制條數(shù)*/ set rowcount @intRowCount select @intBeginID = rootid from bbs where fatherid=0 and forumid=@a_intForumID order by id desc
/*結(jié)束rootID*/ set @intRowCount = @a_intPageNo * @a_intPageSize /*限制條數(shù)*/ set rowcount @intRowCount select @intEndID = rootid from bbs where fatherid=0 and forumid=@a_intForumID order by id desc
/*恢復系統(tǒng)變量*/ 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
|