MSSQL 分页
使用数据库分页返回用户数据有如下好处:
1、减少服务器磁盘系统地读取压力
2、减少网络流量,减轻网络压力
3、减轻客户端显示数据的压力
4、提高处理效率。
一般而言分页处理分为两种:应用程序中的分页(查询出所有数据)处理和数据库中的分页处理。目前大多数的应用都是在应用程序中借助支持数据分页处理的数据库访问组件(如DataGrid控件)实现分页处理(大部分的分页插件中也是采用的程序分页)。实际上,在数据库中实现分页处理,可以从源头减少数据处理量,效果往往可能更好。
所以我们在需要分页的时候尽量使用数据库分页效果是更好的。
常规的取第n页数据方法为
SELECT TOP PageSize * FROM TableA WHERE Primary_Key NOT IN (SELECT TOP (n-1) * PageSize Primary_Key FROM TableA )
这样的如果改成存储过程大概是这样的
CREATE PROC up_PageView ( @tableName SYSNAME , @colKey NVARCHAR(100) , @pageCurrent INT = 1 , @pageSize INT = 10 , @colShow NVARCHAR(4000) = '' , @colOrder NVARCHAR(200) = '' , @where NVARCHAR(2000) = '' , @pageCount INT OUTPUT ) AS BEGIN IF OBJECT_ID(@tableName) IS NULL BEGIN RAISERROR('the table is not existing!', 16,1) RETURN END IF ISNULL(@colShow,'') = '' SET @colShow = '*' IF ISNULL(@colOrder,'') = '' SET @colOrder = '' ELSE SET @colOrder = 'order by ' + @colOrder IF ISNULL(@where,'') = '' SET @where = '' ELSE SET @where = 'where ' + @where DECLARE @sql NVARCHAR(4000) IF @pageCount IS NULL BEGIN SET @sql = 'select @pageCount = count(*) from ' + @tableName + ' ' + @where EXEC sp_executesql @sql , '@pageCount int output' , @pageCount OUTPUT SET @pageCount = ( @pageCount + @pageSize - 1 ) / @pageSize -- get total pages END IF @pageCurrent = 1 BEGIN SET @sql = N'select top' + N' ' + CONVERT(NVARCHAR(10),@pageSize) + N' ' + @colshow + N' ' + N'from ' + @tableName + N' ' + @where + N' ' + @colOrder EXEC (@sql) END ELSE BEGIN DECLARE @topN INT , @topN1 INT -- set @topN = @pageSize -- set @topN1 = @pageCurrent * @pageSize SET @pageCurrent = @pageCurrent * @pageSize SET @sql = N'select @n = @n - 1, @s = case when @n < ' + CONVERT(NVARCHAR(10),@pageSize) + N' then @s + '','' + quotename(@colKey, N'''''''') ' + N'else ''''' + N' end ' + N' from ' + @tableName + N' ' + @where --make query effect only @pageCurrent records --Query only top @pageCurrent * @pageSize SET ROWCOUNT @pageCurrent EXEC sp_executesql @sql , '@n int, @s nvarchar(max) output' , @pageCurrent , @sql OUTPUT SET ROWCOUNT 0 --recover to default config SET @sql = STUFF(@sql,1,1,N'') -- remove the first ',' --exec the query EXEC (N'select ' + @colShow + N' ' + 'from' + N' ' + @tableName + N' ' + N'where ' + @colKey + N' in (' + @sql + ')' + @colOrder) END END go
但是这种执行起来效率比较低,这样是把 top n 取大量的数据并缓存起来,在关联元表查询出最终结果。
下面我们采用另一种方法,在 sql server 2005 以后增加了一些新的功能如取得排名或顺序的函数(Rank(), Dense_Rank(), Row_Number()), 利用这些新的功能也能进行分页处理,下面以sql server 2005 自带的数据库AdventureWorks为例结合Row_Number() 实现分页处理:
CREATE PROC up_GetPagen ( @pageSize INT , @pageCurrent INT , @countPage INT OUTPUT ) AS BEGIN SELECT * FROM ( SELECT ROW_NUMBER () OVER (ORDER BY id) RowNum,* FROM TableA ) TA WHERE RowNum BETWEEN ( @pageCurrent - 1 ) * @pageSize + 1 AND @pageCurrent * @pageSize ORDER BY Id --另加一个返回总记录数吧。 SELECT @countPage = COUNT(0) FROM TableA END