通用的SQL Server資料庫查詢分頁儲存過程

yuzhangqi發表於2008-11-26

基於web的應用程式,經常要執行返回大量資料的查詢。ASP.Net的DataGrid或者GridView自帶的分頁功能雖然簡單,但是並不適用於對效能和負載要求較高的應用場合。我們希望僅從資料庫返回1頁的資料給web客戶端,而不是返回10000條資料只顯示給使用者20條。

網路上有大量分頁查詢儲存過程的資源,本人也蒐集了一些。現將本人認為最具有通用性、易用性的一個版本帖出來,與大家分享。

Code:

/*
使用說明:本儲存過程可用於單表查詢,或多表連線查詢。支援的查詢物件包括表、檢視、自定義表值函式。
返回結果集:1)指定頁的記錄數量;2)記錄總數
示例:
多表連線:
exec [UP_ListPaging]
'Customers inner join Orders on Customers.CustomerID=Orders.CustomerID',
'Orders.OrderID','Customers.CompanyName,Orders.*',20,0,
'Customers.CustomerID=''ROMEY''','','Customers.CompanyName asc'
單表查詢:
exec [UP_ListPaging]
'Customers',
'CustomerID','',20,0,
'CompanyName>=''ROMEY''','','Customers.CompanyName asc'

表與表函式連線查詢:
exec [UP_ListPaging]
'Customers inner join fn_GetOrdersByCustomer(''SUPRD'') on Customers.CustomerID=fn_GetOrdersByCustomer.CustomerID',
'fn_GetOrdersByCustomer.OrderID','Customers.CompanyName,fn_GetOrdersByCustomer.*',20,0,
'','','Customers.CompanyName asc'

*/

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[UP_ListPaging]

@TableNames VARCHAR(200), --表名,可以是多個表,但不能用別名

@PrimaryKey VARCHAR(100), --主鍵,可以為空,但@Order為空時該值不能為空

@Fields VARCHAR(200), --要取出的欄位,可以是多個表的欄位,可以為空,為空表示select *

@PageSize INT, --每頁記錄數

@CurrentPage INT, --當前頁,0表示第1頁

@Filter VARCHAR(200) = '', --條件,可以為空,不用填 where

@Group VARCHAR(200) = '', --分組依據,可以為空,不用填 group by

@Order VARCHAR(200) = '' --排序,可以為空,為空預設按主鍵升序排列,不用填 order by


AS
BEGIN

DECLARE @SortColumn VARCHAR(200)

DECLARE @Operator CHAR(2)

DECLARE @SortTable VARCHAR(200)

DECLARE @SortName VARCHAR(200)

IF @Fields = ''

SET @Fields = '*'

IF @Filter = ''

SET @Filter = 'WHERE 1=1'

ELSE

SET @Filter = 'WHERE ' + @Filter

IF @Group <>''

SET @Group = 'GROUP BY ' + @Group

IF @Order <> ''

BEGIN

DECLARE @pos1 INT, @pos2 INT

SET @Order = REPLACE(REPLACE(@Order, ' asc', ' ASC'), ' desc', ' DESC')

IF CHARINDEX(' DESC', @Order) > 0

IF CHARINDEX(' ASC', @Order) > 0

BEGIN

IF CHARINDEX(' DESC', @Order) < CHARINDEX(' ASC', @Order)

SET @Operator = '<='

ELSE

SET @Operator = '>='

END

ELSE

SET @Operator = '<='

ELSE

SET @Operator = '>='

SET @SortColumn = REPLACE(REPLACE(REPLACE(@Order, ' ASC', ''), ' DESC', ''), ' ', '')

SET @pos1 = CHARINDEX(',', @SortColumn)

IF @pos1 > 0

SET @SortColumn = SUBSTRING(@SortColumn, 1, @pos1-1)

SET @pos2 = CHARINDEX('.', @SortColumn)

IF @pos2 > 0

BEGIN

SET @SortTable = SUBSTRING(@SortColumn, 1, @pos2-1)

IF @pos1 > 0

SET @SortName = SUBSTRING(@SortColumn, @pos2+1, @pos1-@pos2-1)

ELSE

SET @SortName = SUBSTRING(@SortColumn, @pos2+1, LEN(@SortColumn)-@pos2)

END

ELSE

BEGIN

SET @SortTable = @TableNames

SET @SortName = @SortColumn

END

END

ELSE

BEGIN

SET @SortColumn = @PrimaryKey

SET @SortTable = @TableNames

SET @SortName = @SortColumn

SET @Order = @SortColumn

SET @Operator = '>='

END

DECLARE @type varchar(50)

DECLARE @prec int

SELECT @type=t.name, @prec=c.prec

FROM sysobjects o

JOIN syscolumns c on o.id=c.id

JOIN systypes t on c.xusertype=t.xusertype

WHERE o.name = @SortTable AND c.name = @SortName

IF CHARINDEX('char', @type) > 0

SET @type = @type + '(' + CAST(@prec AS varchar) + ')'

DECLARE @TopRows INT

SET @TopRows = @PageSize * @CurrentPage + 1


declare @SQL nvarchar(4000)

set @SQL = ''
set @SQL = @SQL + ' DECLARE @SortColumnBegin ' + @type
set @SQL = @SQL + ' SET ROWCOUNT ' + cast(@TopRows as varchar(10))
set @SQL = @SQL + ' SELECT @SortColumnBegin=' + @SortColumn
+ ' FROM ' + @TableNames + ' ' + @Filter + ' '
+ @Group + ' ORDER BY ' + @Order

set @SQL = @SQL + ' SET ROWCOUNT ' + cast(@PageSize as varchar(10))
set @SQL = @SQL + ' SELECT ' + @Fields + ' FROM ' + @TableNames + ' '
+ @Filter + ' AND ' + @SortColumn + '' + @Operator + '
+ @Group + ' ORDER BY ' + @Order

set @SQL = @SQL +
' SELECT COUNT(1) as num FROM '
+ @TableNames + ' ' + @Filter
+ @Group


print @SQL
exec (@SQL)

END
GO

SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO

[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/13651903/viewspace-1013869/,如需轉載,請註明出處,否則將追究法律責任。

相關文章