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

 

posted @ 2015-01-29 09:51  月夜清风  阅读(1530)  评论(0编辑  收藏  举报