實現數據分頁查詢的方案相當多,前台和後台都有很多好方法,這些好方法都有一個共同的特點:在實現分頁的同時,考慮了網絡資源的占有問題。本文要討論的是使用SQL Server存儲過程的實現方法。
引子
在含有ID主鍵(且ID連續)的Tab表中,查找第51行到第100行數據,對應的SQL語句為:
SLECET*FROME tab WHERE ID BETWEEN 51 AND 100
如果ID不連續,或者主鍵為其他,則可以用下SQL語句實現同樣的功能:
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
SELECT TOP 50 * FROM tab WHERE ID NOT IN (SELECT TOP 50 ID FROM tab)
或是
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
SELECT TOP 50 * FROM tab WHERE ID>@lastpage_endidi
如果用變量參數控制輸入行,則使用以下語句:
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
SET ROWCOUNT@pagesize
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
SELECT * FROM tab WHERE ID>@lastpage_endid
問題
對於沒有主鍵的表,可能存在大量重復的記錄,很多SQL Server使用者喜歡用下面的語句:
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
SELECT IDENTITY(INT,1,1) AS ID,* INTO #T FROM tab
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
SELECT * FROM #T WHERE ID BETWEEN 51 AND 100
上面的方法非常笨拙,而且相當耗資源。
分析
對於這種沒有主鍵的表,要實現分頁查詢,筆者認為最好的方法是加一個IDENTITY屬性的主鍵,然後使用文本開頭使用的兩種方法,效率要高得多。在原表中加入IDENTITY屬性的語句如下:
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
ALTER TABLE tab ADD ID INT IDENTITY PRIMARY KEY
並不是所有用戶都有修改表的權限,下面介紹一種通用的方法:使用SQL Server 提供的儲存過程sp_cursoropen。具體用法如下:
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
exec sp_cursoropen @P1 output,@sqlstr
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
exec sp_cursorfetch @P1,16,@begincol,@pagesize
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
exec sp_cursorclose @P1
其中第一句的@P1為生成的游標ID,@sqlstr為定義游標的SLELECT字符串;第二句中@begincol為起始行數,@pagesize為輸出行數;第三句sp_cursorclose意即關閉游標。
解決
以下是筆者編寫的儲存過程,通過傳入表名,分頁取出第N頁數據。
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
Create proc getpage
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
(@tablename varchar (255), @page count int=1,@pagesize int=99999999)--@tablename為表名
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
as
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
begin
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
set nocount on
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
declare @P1 int
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
declare @sqlstr nvarchar(400)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
set @pagecount =(@pagecount-1)*@pagecount+1
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
set @sqlstr=’select * from ’+@tablename
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
exec sp_cursoropen @P1 output,@sqlstr
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
exec sp_cursorfetch @P1,16,@pagecount,@pagesize
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
exec sp_cursorclose @P1
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
end
調用方法
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
exec getpage’tab’,10,100
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
--表名tab ,第10頁,每頁100行。
進階
以上存儲過程比較通用,不過如果適當修改一下,把@sqlstr當作轉入參數,就更靈活了,實現方法如下:
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
Create proc getpage
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
(@sqlstr nvarchar (4000),@pagecont int=1,@pagesize int=99999999)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
as
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
begin
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
set nocount on
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
declare @P1 int
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
set @pagecount =(@pagecount-1)*@pagecount+1
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
exec sp_cursoropen @P1 output,@sqlstr
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
exec sp_cursorfetch @P1,16,@pagecount,@pagesize
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
exec sp_cursorclose @P1
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
end
調用方法:
![](https://www.aspphp.online/shujuku/UploadFiles_3118/201701/2017011212012748.gif)
exec getpage’SELECT * FROM tab WHERE條件 ’,10,100