set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER proc [dbo].[SqlDataPaging]
@tbName varchar(255),        --表名
@tbFields varchar(1000),      --返回字段
@OrderField varchar(255),  --排序的字段名
@PageSize int,                --页尺寸
@PageIndex int,                --页码
@OrderType bit,                --排序类型,1是升序,0是降序
@strWhere varchar(1500),    --查询条件
@Total int output            --返回总记录数
as
declare @strSql varchar(5000)    --主语句
declare @strOrder varchar(200)    --排序
declare @strSqlCount nvarchar(500)--查询记录总数主语句
--------------排序-----------------1是降序,0未升序
if @OrderType !=0
begin
set @strOrder='order by ' + @OrderField + ' asc '
end
else
begin
set @strOrder='order by '+ @OrderField + ' desc '
end
--------------总记录数---------------
if @strWhere !=''
begin
set @strSqlCount='Select @TotalCout=count(*) from  ' + @tbName + ' where '+ @strWhere
end
else
begin
set @strSqlCount='Select @TotalCout=count(*) from  ' + @tbName
end
--------------开始分页------------
if @PageIndex <= 0
begin
  set @PageIndex = 1
end
if @strWhere !=''
begin
set @strSql='Select * from (Select  row_number() over('+@strOrder+') rowId,'+ @tbFields
+' from ' + @tbName + ' where ' + @strWhere+' ) tb where tb.rowId >'+str((@PageIndex-1)*@PageSize)
+' and tb.rowId <= ' +str(@PageIndex*@PageSize)
end
else
begin
set @strSql='Select * from (Select  row_number() over('+@strOrder+') rowId,'+ @tbFields
+' from ' + @tbName +' ' +' ) tb where tb.rowId > '+str((@PageIndex-1)*@PageSize)
+' and tb.rowId <= ' +str(@PageIndex*@PageSize)
end
exec sp_executesql @strSqlCount,N'@TotalCout int output',@Total output
exec(@strSql)

解决方案 »

  1.   

    2005的分页使用row_number()函数 的确很容易
    帮你建立了编号
      

  2.   


    那你是用top颠倒法。
    不过这个方法需要主键的。
      

  3.   

    row_number() 可能会进行全表计数,快不了哪里去.其实有些时候,没必要用这个总数.
      

  4.   

     sql2005以上可用 row_number()函数
      

  5.   

    CREATE PROCEDURE dbo.GetPagedMovies2005
    (
    @StartRowIndex INT,
    @MaximumRows INT
    )
    AS
    WITH OrderedMovies AS
    (
    SELECT
    Id,
    ROW_NUMBER() OVER (ORDER BY Id) AS RowNumber
    FROM Movies
    )

    SELECT
    OrderedMovies.RowNumber,
    Movies.Id,
    Movies.Title,
    Movies.Director
    FROM
    OrderedMovies
    JOIN Movies
    ON OrderedMovies.Id = Movies.Id
    WHERE
    RowNumber BETWEEN (@StartRowIndex + 1) AND (@startRowIndex + @maximumRows + 1)好像很多大牛都喜欢这样的
      

  6.   

        这个是我简单的表结构
      
    300W数据 
      
    400W数据 
       当然我给time 加了个索引`` 
      

  7.   


    这个,如果想对"任一字段"都达到高效,并且还要基于这个字段排序,如果没有针对这个字段建立索引,那肯定会导致全表扫描.实际应用中,会有这种情况(表中任一字段的排序查询)出现吗?
    最多是3-5个关键字段吧.这还可以考虑建索引
    如果想为表中过多的字段建索引,那是不可取的.我所涉及到的应用中,一般是基于自增ID排序,或者时间排序.所以没考虑到这么复杂.PS:如果只是少数人,譬如管理员在后台查看一些数据,就算用到全表扫描,也可以接受.建议你到SQL版去发个贴,看高手们有何好办法.
      

  8.   


      当然 一个表中不能有很多索引` 但一般有3-5个就差不多了``   实际应用中,会有这种情况(表中任一字段的排序查询)出现吗?
        并不是要针对任意字段 ` 只不过考虑到它的通用性` 
       譬如我上次用了别人的一个存储 我做了一个投票系统要对票数就行排序` 当票数一致时就出现问题了` 
       所以自己写了个比较通用的` 但是对于千万数据 此法不可取 ` row_number() 因为会进行全表计数
      

  9.   

        弱弱的说一句`:  其实csdn 就我知道 .net 估计就这里人比较多把` 高手也很多` 
    所以帖子就发这了`` 
      

  10.   

    select   top   100   *   from   test   A   where   (   select   count(*)   from   test   where   id <A.id   )   > =   500   order   by   id-------
     TOP颠倒法
      

  11.   

      TOP颠倒法  似乎 不怎么样`
      

  12.   

      其实我一开始使用的也是 TOP颠倒法  但是不能达到通用`` 
      

  13.   


    select top '每页显示条数' * from '表'  where  id not in 
     (select top ('每页显示条数' * ('第几页'-1)) id from '表') 我一般这样写的, 不知你能用不
      

  14.   


      以前我也是这样写的 不过 用 not in  的效率很差 ` 
             上百万数据` 就更不用说了` 
      

  15.   

    高手顺便帮我看看哈
    http://topic.csdn.net/u/20100609/12/5a8a7c3f-8048-47c9-9dce-14c6029e4380.html?28483
      

  16.   

    row_number() 真的很快,我们测试过了,100万条数据1秒时间