SQL Server分页存储过程实践(图解)
? ? 下面來對SQL Server分頁存儲過程進(jìn)行一下實做。圖解成功的各個步驟。
一 找到大數(shù)據(jù)量的示例表
? ? 分頁都是針對大記錄數(shù)的表;反之有大記錄數(shù)的表,可能就需要分頁。例如銀行用戶表,就會上千萬。下面先做一個示例的大記錄數(shù)的表。
? ? 先安裝一下動網(wǎng)論壇,用他的數(shù)據(jù)庫來做示例;
下載動網(wǎng)論壇并解壓;
安裝;
安裝到此步出錯了;如果裝上,SQL Server中就會有動網(wǎng)論壇的數(shù)據(jù)庫;
可能是IIS沒裝;在Win7中裝IIS,我選的功能如下;
一直裝不上,都是檢測論壇目錄不成功;估計D盤下的目錄配置為不可寫;這是網(wǎng)管干的;只好不裝了;那么下面采取單獨(dú)把動網(wǎng)的數(shù)據(jù)庫腳本在sqlserver中執(zhí)行來建立數(shù)據(jù)庫;把他的好幾千行的腳本拷進(jìn)sqlserver,執(zhí)行一下,出錯了;
根據(jù)錯誤提示;刪除掉該腳本創(chuàng)建存儲過程的部分,再執(zhí)行,成功了;在測試數(shù)據(jù)庫testdb中創(chuàng)建了表和插入數(shù)據(jù);
執(zhí)行下圖的SQL,看下表的記錄數(shù)夠不夠做分頁實驗;
? ? 不夠;
再繼續(xù)裝動網(wǎng)論壇,看能不能裝上用用,從 運(yùn)行 窗口啟動IIS管理器;
新建一個網(wǎng)站,如下圖;這是動網(wǎng)論壇安裝說明上所說安裝前需要做的;
各位一定想說,你不是分頁么,怎么去裝動網(wǎng)論壇,思維怎么如此飄忽?你問我,我問誰?
不急,下面不久會開始分頁的;
再裝,都是這個錯誤;
從瀏覽器中執(zhí)行動網(wǎng)的首頁,顯示下圖錯誤;
需要把應(yīng)用程序池模式由集成改為托管;
再執(zhí)行首頁;出現(xiàn)下圖錯誤;
根據(jù)錯誤啟用目錄瀏覽;
執(zhí)行首頁時顯示了如下錯誤;看來還是要安裝才行;由于對D盤無寫權(quán)限;先罷了吧。不過對動網(wǎng)論壇還是多了一些了解了;
下面寫一個SQL語句塊,來對表中插入60000條測試數(shù)據(jù);代碼和插入結(jié)果如下圖;成功插入6萬條數(shù)據(jù);
下面來寫第一個分頁存儲過程并執(zhí)行;代碼如下;
set ANSI_NULLS ON
set QUOTED_IDENTIFIER OFF
GO
--SQL SERVER 2000中的TOP分頁
ALTER PROCEDURE [dbo].[dv_bbsnews_GetItemsPage]
? ? @PageIndex INT, /*@PageIndex從計數(shù),0為第一頁*/
? ? @PageSize ?INT, /*頁面大小*/
? ? @RecordCount INT OUT, /*總記錄數(shù)*/
? ? @PageCount INT OUT /*頁數(shù)*/
AS
/*獲取記錄數(shù)*/
SELECT @RecordCount = COUNT(*) FROM dv_bbsnews
/*計算頁面數(shù)據(jù)*/
SET @PageCount = CEILING(@RecordCount * 1.0 / @PageSize)
/*TOP記錄數(shù)*/
DECLARE @TOPCOUNT INT
SET @TOPCOUNT = @RecordCount - @PageSize * @PageIndex?
DECLARE @SQLSTR NVARCHAR(1000)?
IF @PageIndex = 0 OR @PageCount <= 1
BEGIN
? ? SET @SQLSTR =N'SELECT TOP '+STR(@PageSize)+
? ? 'id,boardid,title,content,addtime FROM dv_bbsnews ORDER BY id'
END
ELSE
BEGIN?
? ? IF @PageIndex = @PageCount - 1
? ? BEGIN
? ? ? ?SET @SQLSTR =N'SELECT * FROM ( SELECT TOP ' + STR(@TOPCOUNT) +
? ? ? ?'id,boardid,title,content,addtime FROM dv_bbsnews ORDER BY id ASC) T ORDER BY id DESC'
? ? END
? ? ELSE
? ? BEGIN
? ? ? ?SET @SQLSTR =N' SELECT TOP '+STR(@PageSize)+'* FROM (SELECT TOP ' + STR(@TOPCOUNT) +
? ? ? ?'id,boardid,title,content,addtime FROM dv_bbsnews ORDER BY id ASC) T ORDER BY id DESC'
? ? END
END
EXEC (@SQLSTR)
添加存儲過程成功;執(zhí)行和結(jié)果畫面如下;取第0頁,每頁1萬條;顯示了下述的結(jié)果;
再寫第二個分頁存儲過程;代碼如下;
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[dv_bbsnews_GetItemsPage2005]
? ? @PageIndex INT,
? ? @PageSize ?INT,
? ? @RecordCount INT OUT,
? ? @PageCount INT OUT
AS?
/*獲取記錄數(shù)*/
SELECT @RecordCount = COUNT(*) FROM dv_bbsnews
/*計算頁面數(shù)據(jù)*/
SET @PageCount = CEILING(@RecordCount * 1.0 / @PageSize)
/* 基于SQL SERVER 2005 */
SELECT id,boardid,title,content,addtime FROM
(SELECT id,boardid,title,content,addtime,ROW_NUMBER() OVER (ORDER BY id DESC) AS SerialNumber FROM dv_bbsnews ) AS T
WHERE T.SerialNumber > (@PageIndex * @PageSize) ?and T.SerialNumber <= ((@PageIndex+1) * @PageSize)
? ? 這是基于SQL server 2005以上的新特性,用ROW_NUMBER分的頁;存儲過程代碼如下圖;
執(zhí)行一下;假設(shè)取第0頁;每頁6000條,結(jié)果如下圖;
下面再做一個比較通用的分頁存儲過程;這個和上面兩個不同;上面是針對固定表;這個要分頁的表的名字是作為參數(shù)輸入的;
代碼;
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
?
ALTER PROCEDURE [dbo].[proc_DataPagingList]
(
@tableName NVARCHAR(200), ? ? ?----要顯示的表或多個表的連接
@fieldNames NVARCHAR(200)='*', ----要顯示的字段列表
@pageSize INT = 3000, ? ? ? ? ? ?----每頁顯示的記錄個數(shù)
@page INT = 10, ? ? ? ? ? ? ? ?----要顯示那一頁的記錄
@pageCount INT = 1 output, ? ? ----查詢結(jié)果分頁后的總頁數(shù)
@counts INT = 1 output, ? ? ? ?----查詢到的總記錄數(shù)
@fieldSort NVARCHAR(200)= null,----排序字段列表或條件
@sort BIT = 1, ? ? ? ? ? ? ? ? ----排序方法,0為升序,1為降序--程序傳參如:' SortA Asc,SortB Desc,SortC ')
@condition NVARCHAR(200)= null,----查詢條件,不需WHERE
@keyID NVARCHAR(100), ? ? ? ? ?----主表的主鍵
@distinct BIT = 0 ? ? ? ? ? ? ?----是否添加查詢字段的 DISTINCT 默認(rèn)0不添加/1添加
)
AS
?
SET NOCOUNT ON
Declare @SELECT NVARCHAR(1000) ? ?----存放動態(tài)生成的SQL語句
Declare @strCounts NVARCHAR(1000) ----存放取得查詢結(jié)果總數(shù)的查詢語句
Declare @strID ?NVARCHAR(1000) ? ?----存放取得查詢開頭或結(jié)尾ID的查詢語句
?
Declare @sortTypeA NVARCHAR(10) ? ----數(shù)據(jù)排序規(guī)則A
Declare @SortTypeB NVARCHAR(10) ? ----數(shù)據(jù)排序規(guī)則B
?
Declare @distSelect NVARCHAR(50) ?----對含有DISTINCT的查詢進(jìn)行SQL構(gòu)造
Declare @distCounts NVARCHAR(50) ?----對含有DISTINCT的總數(shù)查詢進(jìn)行SQL構(gòu)造
?
DECLARE @SortfieldA NVARCHAR(50) ?----對含有是否還有排序字段時的排序方式組合A
DECLARE @SortfieldB NVARCHAR(50) ?----對含有是否還有排序字段時的排序方式組合B
?
?
IF @distinct = 0
? ? BEGIN
? ? ? ? SET @distSelect = 'SELECT '
? ? ? ? SET @distCounts = ' COUNT(*)'
? ? END
ELSE
? ? BEGIN
? ? ? ? SET @distSelect = 'SELECT distinct '
? ? ? ? SET @distCounts = ' COUNT(DISTINCT '+@keyID+')'
? ? END
?
IF @sort=0
? ? BEGIN
? ? ? ? SET @SortTypeB=' ASC '
? ? ? ? SET @sortTypeA=' DESC '
? ? END
ELSE
? ? BEGIN
? ? ? ? SET @SortTypeB=' DESC '
? ? ? ? SET @sortTypeA=' ASC '
? ? END
?
IF @fieldSort IS NOT NULL AND @fieldSort<>'' --排序字段不為空時
? ? BEGIN
? ? ? ? SET @SortfieldB=' order by '+ @fieldSort +' '+ @SortTypeB
? ? ? ? SET @SortfieldA=' order by '+ @fieldSort +' '+ @SortTypeA?
? ? END
ELSE
? ? BEGIN
? ? ? ? SET @SortfieldB=''
? ? ? ? SET @SortfieldA=''
? ? END
?
--------生成查詢語句--------
--此處@strCounts為取得查詢結(jié)果數(shù)量的語句
IF @condition is null or @condition='' ? ? --沒有設(shè)置顯示條件
? ? BEGIN
? ? ? ? SET @SELECT = ?@fieldNames + ' FROM ' + @tableName
? ? ? ? SET @strCounts = @distSelect+' @counts='+@distCounts+' FROM '+@tableName
? ? ? ? SET @strID = ' FROM ' + @tableName
? ? END
ELSE
? ? BEGIN
? ? ? ? SET @SELECT = + @fieldNames + 'FROM ' + @tableName + ' WHERE ?' + @condition
? ? ? ? SET @strCounts = @distSelect+' @counts='+@distCounts+' FROM '+@tableName + ' WHERE ' + @condition
? ? ? ? SET @strID = ' FROM ' + @tableName + ' WHERE ?' + @condition
? ? END
?
----取得查詢結(jié)果總數(shù)量-----
exec sp_executesql @strCounts,N'@counts INT out ',@counts out
DECLARE @tmpCounts INT
?
IF @counts = 0
? ? SET @tmpCounts = 1
ELSE
? ? SET @tmpCounts = @counts
?
? ? --取得分頁總數(shù)
? ? SET @pageCount=(@tmpCounts+@pageSize-1)/@pageSize
?
? ? --/**當(dāng)前頁大于總頁數(shù) 取最后一頁**/
? ? IF @page>@pageCount
? ? ? ? SET @page=@pageCount
?
? ? --/*-----數(shù)據(jù)分頁2分處理-------*/
? ? DECLARE @pageIndex INT --總數(shù)/頁大小
? ? DECLARE @lastcount INT --總數(shù)%頁大小?
?
? ? SET @pageIndex = @tmpCounts/@pageSize
? ? SET @lastcount = @tmpCounts%@pageSize
? ? IF @lastcount > 0
? ? ? ? SET @pageIndex = @pageIndex + 1
? ? ELSE
? ? ? ? SET @lastcount = @pageSize
?
? ? --顯示分頁
? ? IF @condition is null or @condition='' ? ? --沒有設(shè)置顯示條件
? ? BEGIN
? ? ? ? IF @pageIndex<2 or @page<=@pageIndex / 2 + @pageIndex % 2 ? --前半部分?jǐn)?shù)據(jù)處理
? ? ? ? ? ? BEGIN
? ? ? ? ? ? ? ? SET @strCounts=@distSelect+' TOP '+ CAST(@pageSize as VARCHAR(4))+' '+ @fieldNames+' FROM '+@tableName + ' WHERE '+@keyID+' not in('+ @distSelect+' TOP '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @keyID +' FROM '+@tableName + @SortfieldB +')' + @SortfieldB?
? ? ? ? ? ? END
? ? ? ? ELSE
? ? ? ? ? ? BEGIN
? ? ? ? ? ? SET @page = @pageIndex-@page+1 --后半部分?jǐn)?shù)據(jù)處理
? ? ? ? ? ? ? ? IF @page <= 1 --最后一頁數(shù)據(jù)顯示
? ? ? ? ? ? ? ? ? ? SET @strCounts=@distSelect+' * FROM ('+@distSelect+' TOP '+ CAST(@lastcount as VARCHAR(4))+' '+ @fieldNames+' FROM '+@tableName + @SortfieldA+') AS TempTB '+@SortfieldB
? ? ? ? ? ? ? ? ELSE ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? SET @strCounts=@distSelect+' * FROM ('+@distSelect+' TOP '+ CAST(@pageSize as VARCHAR(4))+' '+ @fieldNames+' FROM '+@tableName + ' WHERE '+@keyID+' not in('+ @distSelect+' TOP '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' '+ @keyID +' FROM '+@tableName + @SortfieldA+')' + @SortfieldA+') AS TempTB '+@SortfieldB
? ? ? ? ? ? END
? ? END
?
? ? ELSE --有查詢條件
? ? BEGIN
? ? ? ? IF @pageIndex<2 or @page<=@pageIndex / 2 + @pageIndex % 2 ? --前半部分?jǐn)?shù)據(jù)處理
? ? ? ? BEGIN
? ? ? ? ? ? ? ? SET @strCounts=@distSelect+' TOP '+ CAST(@pageSize as VARCHAR(4))+' '+ @fieldNames +' FROM ?'+@tableName + ' WHERE '+@keyID+' not in('+ @distSelect+' TOP '+ CAST(@pageSize*(@page-1) as Varchar(20)) +' '+ @keyID +' FROM '+@tableName + ' Where ' + @condition + @SortfieldB+')'+' AND ' + @condition + @SortfieldB ? ? ? ? ? ? ? ??
? ? ? ? END
? ? ? ? ELSE
? ? ? ? BEGIN
? ? ? ? ? ? SET @page = @pageIndex-@page+1 --后半部分?jǐn)?shù)據(jù)處理
? ? ? ? ? ? IF @page <= 1 --最后一頁數(shù)據(jù)顯示
? ? ? ? ? ? ? ? ? ? SET @strCounts=@distSelect+' * FROM ('+@distSelect+' TOP '+ CAST(@lastcount as VARCHAR(4))+' '+ @fieldNames+' FROM '+@tableName + ' WHERE ?'+ @condition +@SortfieldA+') AS TempTB '+@SortfieldB
? ? ? ? ? ? ELSE
? ? ? ? ? ? ? ? ? ? SET @strCounts=@distSelect+' * FROM ('+@distSelect+' TOP '+ CAST(@pageSize as VARCHAR(4))+' '+ @fieldNames+' FROM '+@tableName + ' WHERE '+@keyID+' not in('+ @distSelect+' TOP '+ CAST(@pageSize*(@page-2)+@lastcount as Varchar(20)) +' ' + @keyID +' FROM '+@tableName +' WHERE ?'+ @condition +@SortfieldA+')' +' AND '+ @condition +@SortfieldA+') AS TempTB ' + @SortfieldB?
? ? ? ? END ??
? ? END
?
------返回查詢結(jié)果-----
exec sp_executesql @strCounts
SET NOCOUNT OFF
添加存儲過程成功;執(zhí)行一下;假設(shè)取第11頁;每頁數(shù)量如果不輸入,按代碼中所示,默認(rèn)為3000;同時需要輸入主鍵字段的名稱"id";執(zhí)行結(jié)果如下圖;成功取到第11頁的內(nèi)容;
?
? ? 這樣就搞定了三個分頁的存儲過程。
總結(jié)
以上是生活随笔為你收集整理的SQL Server分页存储过程实践(图解)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#接口和编程实例
- 下一篇: 图解Oracle常用SQL语句