針對資料庫資料在ui介面上的分頁是老生常談的問題了,網上很容易找到各種「通用儲存過程」**,而且有些還定製查詢條件,看上去使用很方便。筆者打算通過本文也來簡單談一下基於sql server 2000的分頁儲存過程,同時談談sql server 2005下分頁儲存過程的演進。
在進行基於ui顯示的資料分頁時,常見的資料提取方式主要有兩種。第一種是從資料庫提取所有資料然後在系統應用程式層進行資料分頁,顯示當前頁資料。第二種分頁方式為從資料庫取出需要顯示的一頁資料顯示在ui介面上。
以下是筆者對兩種實現方式所做的優缺點比較,針對應用程式編寫,筆者以.net技術平台為例。
類別 sql語句 **編寫 設計時 效能
第一種 語句簡單,相容性好 很少 完全支援 資料越大效能越差
第二種 看具體情況 較多 部分支援 良好,跟sql語句有關
對於第一種情況本文不打算舉例,第二種實現方式筆者只以兩次top方式來進行討論。
在編寫具體sql語句之前,定義以下資料表。
資料表名稱為:production.product。production為sql server 2005中改進後的資料表架構,對舉例不造成影響。
包含的字段為:
列名 資料型別 允許空 說明
productid int 產品id,pk。
name nvarchar(50) 產品名稱。
不難發現以上表結構來自sql server 2005 樣例資料庫adventureworks的production.product表,並且只取其中兩個字段。
pageindex – 頁面索引計數,計數0為第一頁。
pagesize – 每個頁面顯示大小。
recordcount – 總記錄數。
pagecount – 頁數。
對於後兩個引數,筆者在儲存過程中以輸出引數提供。
1.sql server 2000中的top分頁
create procedure [zhzuo_getitemspage]
@pageindex int, /*@pageindex從計數,0為第一頁*/
@pagesize int, /*頁面大小*/
@recordcount int out, /*總記錄數*/
@pagecount int out /*頁數*/
as/*獲取記錄數*/
select @recordcount = count(*) from production.product
/*計算頁面資料*/
set @pagecount = ceiling(@recordcount * 1.0 / @pagesize)
/*top記錄數*/
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)+
'productid,name from production.product order by productid desc'
endelse
begin
if @pageindex = @pagecount - 1
begin
set @sqlstr =n'select * from ( select top ' + str(@topcount) +
'productid,name from production.product order by productid asc) t order by productid desc'
endelse
begin
set @sqlstr =n' select top '+str(@pagesize)+'* from (select top ' + str(@topcount) +
'productid,name from production.product order by productid asc) t order by productid desc'
endend
/*執行*/
exec (@sqlstr)
以上儲存過程對頁數進行判斷,如果是第一頁或最後一頁,進行特殊處理。其他情況使用2次top翻轉。其中排序條件為productid倒序。最後通過execute執行sql字串拼串。
2.sql server 2005中的top分頁
create procedure [dbo].[zhzuo_getitemspage2005top]
@pageindex int,
@pagesize int,
@recordcount int out,
@pagecount int out
as /*獲取記錄數*/
select @recordcount = count(*) from production.product
/*計算頁面資料*/
set @pagecount = ceiling(@recordcount * 1.0 / @pagesize)
/*top記錄數*/
declare @topcount int
set @topcount = @recordcount - @pagesize * @pageindex
/*基於sql server 2005 */
if @pageindex = 0 or @pagecount <= 1
begin
select top(@pagesize) productid,name from production.product order by productid desc
endelse
begin
if @pageindex = @pagecount - 1
begin
select * from ( select top(@topcount) productid,name from production.product order by productid asc) t
order by productid desc
endelse
begin
select top(@pagesize) * from (select top(@topcount) productid,name from production.product order by productid asc) t
order by productid desc
endend
以上儲存過程是使用2005的top (表示式) 新功能,避免了字串拼串,使結構化查詢語言變得簡潔。實現的為同樣的功能。
3.sql server 2005中的新分頁
create procedure [dbo].[zhzuo_getitemspage2005]
@pageindex int,
@pagesize int,
@recordcount int out,
@pagecount int out
as /*獲取記錄數*/
select @recordcount = count(*) from production.product
/*計算頁面資料*/
set @pagecount = ceiling(@recordcount * 1.0 / @pagesize)
/* 基於sql server 2005 */
select serialnumber,productid,name from
(select productid,name,row_number() over (order by productid desc) as serialnumber from production.product ) as t
where t.serialnumber > (@pageindex * @pagesize) and t.serialnumber <= ((@pageindex+1) * @pagesize)
第三個儲存過程使用2005下新的功能,實現的分頁儲存過程功能更加簡單明瞭,而且更加容易理解。注意這裡的productid為主鍵,根據productid進行排序生成row_number,通過row_number來確定具體的頁數。
通過對三個分頁儲存過程的比較,可見sql server 的tsql 語言對分頁功能的支援進步不少。使分頁實現趨向於簡單化。
資料庫物理分頁和邏輯分頁簡單介紹
目錄 1 物理分頁 物理分頁就是資料庫本身提供了分頁方式,如mysql的limit,好處是效率高,不好的地方就是不同資料庫有不同的搞法。2 邏輯分頁 邏輯分頁利用游標分頁,好處是所有資料庫都統一,壞處就是效率低。3 常用orm框架採用的分頁技術 hibernate採用的是物理分頁 mybatis使用...
資料庫分頁
mysql 分頁採用limt 關鍵字select from t order limit 5,10 返回第6 15 行資料 select from t order limit 5 返回前5 行 select from t order limit 0,5 返回前5 行 mssql 2000 分頁採用to...
資料庫分頁
oracle分頁 方法1 根據rowid來分 select from uop crm1.tf f user where rowid in select rid from select rownum r,rid from select rowid rid from uop crm1.tf f user...