SQL Server 存储过程的分页
 SQL Server 存储过程的分页方案比拼
SQL Server 存储过程的分页方案比拼  SQL Server 存储过程的分页,这个问题已经讨论过几年了,很多朋友在问我,所以在此发表一下我的观点
SQL Server 存储过程的分页,这个问题已经讨论过几年了,很多朋友在问我,所以在此发表一下我的观点 建立表:
建立表:
 CREATE TABLE [TestTable] (
CREATE TABLE [TestTable] ( [ID] [int] IDENTITY (1, 1) NOT NULL ,
 [ID] [int] IDENTITY (1, 1) NOT NULL , [FirstName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,
 [FirstName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL , [LastName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,
 [LastName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL , [Country] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
 [Country] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL , [Note] [nvarchar] (2000) COLLATE Chinese_PRC_CI_AS NULL
 [Note] [nvarchar] (2000) COLLATE Chinese_PRC_CI_AS NULL  ) ON [PRIMARY]
) ON [PRIMARY] GO
GO
 
 
 插入数据:(2万条,用更多的数据测试会明显一些)
插入数据:(2万条,用更多的数据测试会明显一些) SET IDENTITY_INSERT TestTable ON
SET IDENTITY_INSERT TestTable ON
 declare @i int
declare @i int set @i=1
set @i=1 while @i<=20000
while @i<=20000 begin
begin insert into TestTable([id], FirstName, LastName, Country,Note) values(@i, 'FirstName_XXX','LastName_XXX','Country_XXX','Note_XXX')
    insert into TestTable([id], FirstName, LastName, Country,Note) values(@i, 'FirstName_XXX','LastName_XXX','Country_XXX','Note_XXX') set @i=@i+1
    set @i=@i+1 end
end
 SET IDENTITY_INSERT TestTable OFF
SET IDENTITY_INSERT TestTable OFF
 
 
 -------------------------------------
-------------------------------------
 分页方案一:(利用Not In和SELECT TOP分页)
分页方案一:(利用Not In和SELECT TOP分页) 语句形式:
语句形式: SELECT TOP 10 *
SELECT TOP 10 * FROM TestTable
FROM TestTable WHERE (ID NOT IN
WHERE (ID NOT IN (SELECT TOP 20 id
          (SELECT TOP 20 id FROM TestTable
         FROM TestTable ORDER BY id))
         ORDER BY id)) ORDER BY ID
ORDER BY ID

 SELECT TOP 页大小 *
SELECT TOP 页大小 * FROM TestTable
FROM TestTable WHERE (ID NOT IN
WHERE (ID NOT IN (SELECT TOP 页大小*页数 id
          (SELECT TOP 页大小*页数 id FROM 表
         FROM 表 ORDER BY id))
         ORDER BY id)) ORDER BY ID
ORDER BY ID
 -------------------------------------
-------------------------------------
 分页方案二:(利用ID大于多少和SELECT TOP分页)
分页方案二:(利用ID大于多少和SELECT TOP分页) 语句形式:
语句形式: SELECT TOP 10 *
SELECT TOP 10 * FROM TestTable
FROM TestTable WHERE (ID >
WHERE (ID > (SELECT MAX(id)
          (SELECT MAX(id) FROM (SELECT TOP 20 id
         FROM (SELECT TOP 20 id FROM TestTable
                 FROM TestTable ORDER BY id) AS T))
                 ORDER BY id) AS T)) ORDER BY ID
ORDER BY ID

 SELECT TOP 页大小 *
SELECT TOP 页大小 * FROM TestTable
FROM TestTable WHERE (ID >
WHERE (ID > (SELECT MAX(id)
          (SELECT MAX(id) FROM (SELECT TOP 页大小*页数 id
         FROM (SELECT TOP 页大小*页数 id FROM 表
                 FROM 表 ORDER BY id) AS T))
                 ORDER BY id) AS T)) ORDER BY ID
ORDER BY ID

 -------------------------------------
-------------------------------------
 分页方案三:(利用SQL的游标存储过程分页)
分页方案三:(利用SQL的游标存储过程分页) create  procedure XiaoZhengGe
create  procedure XiaoZhengGe @sqlstr nvarchar(4000), --查询字符串
@sqlstr nvarchar(4000), --查询字符串 @currentpage int, --第N页
@currentpage int, --第N页 @pagesize int --每页行数
@pagesize int --每页行数 as
as set nocount on
set nocount on declare @P1 int, --P1是游标的id
declare @P1 int, --P1是游标的id @rowcount int
 @rowcount int exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output
exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output select ceiling(1.0*@rowcount/@pagesize) as 总页数--,@rowcount as 总行数,@currentpage as 当前页
select ceiling(1.0*@rowcount/@pagesize) as 总页数--,@rowcount as 总行数,@currentpage as 当前页  set @currentpage=(@currentpage-1)*@pagesize+1
set @currentpage=(@currentpage-1)*@pagesize+1 exec sp_cursorfetch @P1,16,@currentpage,@pagesize
exec sp_cursorfetch @P1,16,@currentpage,@pagesize  exec sp_cursorclose @P1
exec sp_cursorclose @P1 set nocount off
set nocount off
 其它的方案:如果没有主键,可以用临时表,也可以用方案三做,但是效率会低。
其它的方案:如果没有主键,可以用临时表,也可以用方案三做,但是效率会低。 建议优化的时候,加上主键和索引,查询效率会提高。
建议优化的时候,加上主键和索引,查询效率会提高。
 通过SQL 查询分析器,显示比较:我的结论是:
通过SQL 查询分析器,显示比较:我的结论是: 分页方案二:(利用ID大于多少和SELECT TOP分页)效率最高,需要拼接SQL语句
分页方案二:(利用ID大于多少和SELECT TOP分页)效率最高,需要拼接SQL语句 分页方案一:(利用Not In和SELECT TOP分页)   效率次之,需要拼接SQL语句
分页方案一:(利用Not In和SELECT TOP分页)   效率次之,需要拼接SQL语句 分页方案三:(利用SQL的游标存储过程分页)    效率最差,但是最为通用
分页方案三:(利用SQL的游标存储过程分页)    效率最差,但是最为通用
 在实际情况中,要具体分析。
在实际情况中,要具体分析。

 更多的讨论见:
更多的讨论见: http://community.csdn.net/Expert/topic/3292/3292678.xml?temp=.1621515
http://community.csdn.net/Expert/topic/3292/3292678.xml?temp=.1621515



 Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=103511
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=103511
 [点击此处收藏本文]   发表于 2004年09月14日 1:05 AM
[点击此处收藏本文]   发表于 2004年09月14日 1:05 AM 

 
   squirrel_sc 发表于2004-09-28 8:38 PM  IP: 61.49.220.*
squirrel_sc 发表于2004-09-28 8:38 PM  IP: 61.49.220.* 能否给出具体的测试结果数据呢?谢谢~
能否给出具体的测试结果数据呢?谢谢~
 
   QQ'Richer 发表于2004-10-29 10:12 AM  IP: 219.239.44.*
QQ'Richer 发表于2004-10-29 10:12 AM  IP: 219.239.44.* 好,总算找到这篇文章了,谢谢洪根兄
好,总算找到这篇文章了,谢谢洪根兄
 
   SUN 发表于2004-11-09 10:49 AM  IP: 61.233.144.*
SUN 发表于2004-11-09 10:49 AM  IP: 61.233.144.* declare @pagesize int
declare @pagesize int  set @pagesize = 10
set @pagesize = 10  select top @pagesize * from album
select top @pagesize * from album  order by picid
order by picid 
 这样怎么不对啊?
这样怎么不对啊?  老大!
老大!  select top 10 * from album
select top 10 * from album  order by picid
order by picid  又可以 为什么呢?
又可以 为什么呢?  那我怎么写存储过程啊!
那我怎么写存储过程啊!
 
   SUN 发表于2004-11-09 11:06 AM  IP: 61.233.144.*
SUN 发表于2004-11-09 11:06 AM  IP: 61.233.144.* 那我 不是 不能写成 存储过程?
那我 不是 不能写成 存储过程?  只有写成 SQL语句放在页面上?
只有写成 SQL语句放在页面上?  这样不是会降低性能?
这样不是会降低性能?
 
   hubinasm 发表于2004-11-21 11:51 PM  IP:
hubinasm 发表于2004-11-21 11:51 PM  IP:  TrackBack来自《关于数据库分页》:
TrackBack来自《关于数据库分页》:
 Ping Back来自:blog.csdn.net
Ping Back来自:blog.csdn.net
 
   sunny 发表于2004-12-02 10:25 PM  IP: 61.149.250.*
sunny 发表于2004-12-02 10:25 PM  IP: 61.149.250.* 第二种办法,如果按照主键排序可以。
第二种办法,如果按照主键排序可以。 
 不然的话不行。
不然的话不行。 

 
   菩提树 发表于2004-12-08 6:06 PM  IP: 219.133.133.*
菩提树 发表于2004-12-08 6:06 PM  IP: 219.133.133.* 很多情况下,我们可能不能按主键来排序并分页,比如,你可能需要按工资高低给20万条记录分页及排序,那你肯定只能用临时表或者游标了,游标我不熟,临时表倒是可以达到目的,可是效率不好呀
很多情况下,我们可能不能按主键来排序并分页,比如,你可能需要按工资高低给20万条记录分页及排序,那你肯定只能用临时表或者游标了,游标我不熟,临时表倒是可以达到目的,可是效率不好呀  ALTER PROCEDURE dbo.GetPageRecord
ALTER PROCEDURE dbo.GetPageRecord  (
(  @tblName varchar(255), -- 表名
@tblName varchar(255), -- 表名  @fldName varchar(255), --排序字段
@fldName varchar(255), --排序字段  @KeyField varchar(255), --主键
@KeyField varchar(255), --主键  @PageSize int = 10, -- 页尺寸
@PageSize int = 10, -- 页尺寸  @PageIndex int = 1, -- 页码
@PageIndex int = 1, -- 页码  @IsCount bit = 0, -- 返回记录总数, 非 0 值则返回
@IsCount bit = 0, -- 返回记录总数, 非 0 值则返回  @OrderType bit = 1, -- 设置排序类型, 非 0 值则降序
@OrderType bit = 1, -- 设置排序类型, 非 0 值则降序  @strWhere varchar(4000) = '' -- 查询条件 (注意: 不要加 where)
@strWhere varchar(4000) = '' -- 查询条件 (注意: 不要加 where)  )
)  AS
AS  SET NOCOUNT ON
SET NOCOUNT ON  DECLARE @PageLowerBound int
DECLARE @PageLowerBound int  DECLARE @PageUpperBound int
DECLARE @PageUpperBound int 
 -- Set the page bounds
-- Set the page bounds  SET @PageLowerBound = @PageSize * @PageIndex
SET @PageLowerBound = @PageSize * @PageIndex  SET @PageUpperBound = @PageLowerBound + @PageSize + 1
SET @PageUpperBound = @PageLowerBound + @PageSize + 1 
 -- Create a temp table to store the select results
-- Create a temp table to store the select results  CREATE TABLE #tmp
CREATE TABLE #tmp  (
(  RecNo int IDENTITY (1, 1) NOT NULL,
RecNo int IDENTITY (1, 1) NOT NULL,  oldid int
oldid int  )
)  --generate record
--generate record  Declare @Sqlstr varchar(6000)
Declare @Sqlstr varchar(6000)  set @sqlstr='select '+@Keyfield+' from '+@tblname
set @sqlstr='select '+@Keyfield+' from '+@tblname  if(@strWhere<>'')
if(@strWhere<>'')  begin
begin  set @Sqlstr=@sqlstr+' where ('+@strWhere+')'
set @Sqlstr=@sqlstr+' where ('+@strWhere+')'  end
end  set @sqlstr=@sqlstr+' order by '+@fldName
set @sqlstr=@sqlstr+' order by '+@fldName  if(@ordertype=0)
if(@ordertype=0)  begin
begin  set @sqlstr=@sqlstr+' asc'
set @sqlstr=@sqlstr+' asc'  end
end  else
else  begin
begin  set @sqlstr=@sqlstr+' desc'
set @sqlstr=@sqlstr+' desc'  end
end  set @sqlstr='insert into #tmp (oldid) '+@sqlstr
set @sqlstr='insert into #tmp (oldid) '+@sqlstr  execute(@sqlstr)
execute(@sqlstr)  set @sqlstr='SELECT TableA.* FROM '+@tblname+' TableA (nolock), #tmp T WHERE T.oldid = TableA.'+@keyfield+' AND T.RecNo > '+ cast(@PageLowerBound as varchar)+' AND T.RecNo < '+cast(@PageUpperBound as varchar)+' ORDER BY T.RecNo'
set @sqlstr='SELECT TableA.* FROM '+@tblname+' TableA (nolock), #tmp T WHERE T.oldid = TableA.'+@keyfield+' AND T.RecNo > '+ cast(@PageLowerBound as varchar)+' AND T.RecNo < '+cast(@PageUpperBound as varchar)+' ORDER BY T.RecNo'  execute(@sqlstr)
execute(@sqlstr)
 
   菩提树 发表于2004-12-08 6:06 PM  IP: 219.133.133.*
菩提树 发表于2004-12-08 6:06 PM  IP: 219.133.133.* ALTER PROCEDURE dbo.GetPageRecord
ALTER PROCEDURE dbo.GetPageRecord  (
(  @tblName varchar(255), -- 表名
@tblName varchar(255), -- 表名  @fldName varchar(255), --排序字段
@fldName varchar(255), --排序字段  @KeyField varchar(255), --主键
@KeyField varchar(255), --主键  @PageSize int = 10, -- 页尺寸
@PageSize int = 10, -- 页尺寸  @PageIndex int = 1, -- 页码
@PageIndex int = 1, -- 页码  @IsCount bit = 0, -- 返回记录总数, 非 0 值则返回
@IsCount bit = 0, -- 返回记录总数, 非 0 值则返回  @OrderType bit = 1, -- 设置排序类型, 非 0 值则降序
@OrderType bit = 1, -- 设置排序类型, 非 0 值则降序  @strWhere varchar(4000) = '' -- 查询条件 (注意: 不要加 where)
@strWhere varchar(4000) = '' -- 查询条件 (注意: 不要加 where)  )
)  AS
AS  SET NOCOUNT ON
SET NOCOUNT ON  DECLARE @PageLowerBound int
DECLARE @PageLowerBound int  DECLARE @PageUpperBound int
DECLARE @PageUpperBound int 
 -- Set the page bounds
-- Set the page bounds  SET @PageLowerBound = @PageSize * @PageIndex
SET @PageLowerBound = @PageSize * @PageIndex  SET @PageUpperBound = @PageLowerBound + @PageSize + 1
SET @PageUpperBound = @PageLowerBound + @PageSize + 1 
 -- Create a temp table to store the select results
-- Create a temp table to store the select results  CREATE TABLE #tmp
CREATE TABLE #tmp  (
(  RecNo int IDENTITY (1, 1) NOT NULL,
RecNo int IDENTITY (1, 1) NOT NULL,  oldid int
oldid int  )
)  --generate record
--generate record  Declare @Sqlstr varchar(6000)
Declare @Sqlstr varchar(6000)  set @sqlstr='select '+@Keyfield+' from '+@tblname
set @sqlstr='select '+@Keyfield+' from '+@tblname  if(@strWhere<>'')
if(@strWhere<>'')  begin
begin  set @Sqlstr=@sqlstr+' where ('+@strWhere+')'
set @Sqlstr=@sqlstr+' where ('+@strWhere+')'  end
end  set @sqlstr=@sqlstr+' order by '+@fldName
set @sqlstr=@sqlstr+' order by '+@fldName  if(@ordertype=0)
if(@ordertype=0)  begin
begin  set @sqlstr=@sqlstr+' asc'
set @sqlstr=@sqlstr+' asc'  end
end  else
else  begin
begin  set @sqlstr=@sqlstr+' desc'
set @sqlstr=@sqlstr+' desc'  end
end  set @sqlstr='insert into #tmp (oldid) '+@sqlstr
set @sqlstr='insert into #tmp (oldid) '+@sqlstr  execute(@sqlstr)
execute(@sqlstr)  set @sqlstr='SELECT TableA.* FROM '+@tblname+' TableA (nolock), #tmp T WHERE T.oldid = TableA.'+@keyfield+' AND T.RecNo > '+ cast(@PageLowerBound as varchar)+' AND T.RecNo < '+cast(@PageUpperBound as varchar)+' ORDER BY T.RecNo'
set @sqlstr='SELECT TableA.* FROM '+@tblname+' TableA (nolock), #tmp T WHERE T.oldid = TableA.'+@keyfield+' AND T.RecNo > '+ cast(@PageLowerBound as varchar)+' AND T.RecNo < '+cast(@PageUpperBound as varchar)+' ORDER BY T.RecNo'  execute(@sqlstr)
execute(@sqlstr)
 
   3doyang 发表于2005-02-15 7:14 PM  IP:
3doyang 发表于2005-02-15 7:14 PM  IP:  TrackBack来自《ASP.NET分页的处理方式》:
TrackBack来自《ASP.NET分页的处理方式》:
 Ping Back来自:blog.csdn.net
Ping Back来自:blog.csdn.net
 
   Nill 发表于2005-03-05 1:44 AM  IP: 219.128.247.*
Nill 发表于2005-03-05 1:44 AM  IP: 219.128.247.* 我改了下方案2
我改了下方案2 
 declare @pagesize int
declare @pagesize int  declare @pagenum int
declare @pagenum int  set @pagenum=3---第几页
set @pagenum=3---第几页  set @pagesize=20 ----每页显示条目数
set @pagesize=20 ----每页显示条目数 
 declare @t0 varchar(10)
declare @t0 varchar(10)  declare @t1 varchar(10)
declare @t1 varchar(10) 
 set @t0=cast(@pagesize as varchar(10))
set @t0=cast(@pagesize as varchar(10))  set @t1=cast(@pagesize*(@pagenum-1) as varchar(10))
set @t1=cast(@pagesize*(@pagenum-1) as varchar(10))  --加了个判断是否是第一页。
--加了个判断是否是第一页。  if @pagenum<>1
if @pagenum<>1  exec('SELECT TOP '+@t0+ ' * FROM DV_board WHERE (boardid >(SELECT MAX(boardid) FROM (SELECT TOP '+@t1+ ' boardid FROM DV_board ORDER BY boardid) AS T)) ORDER BY boardID')
exec('SELECT TOP '+@t0+ ' * FROM DV_board WHERE (boardid >(SELECT MAX(boardid) FROM (SELECT TOP '+@t1+ ' boardid FROM DV_board ORDER BY boardid) AS T)) ORDER BY boardID')  else
else  exec('SELECT TOP '+@t0+ ' * FROM DV_board')
exec('SELECT TOP '+@t0+ ' * FROM DV_board')
 
   曾登高 发表于2005-03-28 1:11 AM  IP:
曾登高 发表于2005-03-28 1:11 AM  IP:  TrackBack来自《近日关注:系统性能提升之道--内存镜像表》:
TrackBack来自《近日关注:系统性能提升之道--内存镜像表》:
 Ping Back来自:blog.csdn.net
Ping Back来自:blog.csdn.net
 
   我是好猫 发表于2005-03-29 8:49 PM  IP: 218.58.242.*
我是好猫 发表于2005-03-29 8:49 PM  IP: 218.58.242.* 什么时候,盖子能推出个 适合分页(类似 mysql 的 LIMIT )的 新mssql版本啊 。。。。
什么时候,盖子能推出个 适合分页(类似 mysql 的 LIMIT )的 新mssql版本啊 。。。。 
 
   九命鸟 发表于2005-04-20 5:10 PM  IP: 210.22.100.*
九命鸟 发表于2005-04-20 5:10 PM  IP: 210.22.100.* 这样分页的方例都不是很通用,可以考虑用Rowcount的方法,参数@table, @fields, @filter, @orderby, @groupby, @pagenumber, @pagesize,在SP中形成SQL语句。
这样分页的方例都不是很通用,可以考虑用Rowcount的方法,参数@table, @fields, @filter, @orderby, @groupby, @pagenumber, @pagesize,在SP中形成SQL语句。
 
   随身影子 发表于2005-04-22 12:48 PM  IP: 219.137.167.*
随身影子 发表于2005-04-22 12:48 PM  IP: 219.137.167.* 如果输出按字段AA排序,并且 AA 是索引的话,用游标是最高效率的。用游标分两次分别取到Begin和End点的AA的值就可以搞定。
如果输出按字段AA排序,并且 AA 是索引的话,用游标是最高效率的。用游标分两次分别取到Begin和End点的AA的值就可以搞定。 

 
   王者归来 发表于2005-06-01 10:54 PM  IP: 61.186.252.*
王者归来 发表于2005-06-01 10:54 PM  IP: 61.186.252.* 两个问题:1.用方法2,如何选择第一页的数据,pagesize和pagecount分别怎么传? 2.如何实现主从表数据的分页?
两个问题:1.用方法2,如何选择第一页的数据,pagesize和pagecount分别怎么传? 2.如何实现主从表数据的分页?
 
   王者归来 发表于2005-06-01 10:57 PM  IP: 61.186.252.*
王者归来 发表于2005-06-01 10:57 PM  IP: 61.186.252.* To 九命鸟:老兄说的这种方法哪里可以找到参考?
To 九命鸟:老兄说的这种方法哪里可以找到参考?
 
   ξσ Dicky σξ 发表于2005-06-18 10:36 AM  IP:
ξσ Dicky σξ 发表于2005-06-18 10:36 AM  IP:  TrackBack来自《SQL Server 存储过程的分页方案比拼》:
TrackBack来自《SQL Server 存储过程的分页方案比拼》:
 Ping Back来自:blog.csdn.net
Ping Back来自:blog.csdn.net
 
   leeight 发表于2005-07-12 10:38 AM  IP:
leeight 发表于2005-07-12 10:38 AM  IP:  TrackBack来自《关于存储过程实现分页的技术》:
TrackBack来自《关于存储过程实现分页的技术》:
 Ping Back来自:blog.csdn.net
Ping Back来自:blog.csdn.net
 
   小灰 发表于2005-07-21 8:59 PM  IP: 61.186.252.*
小灰 发表于2005-07-21 8:59 PM  IP: 61.186.252.* 看看这个效率如何?怎么改进?
看看这个效率如何?怎么改进?  CREATE proc page
CREATE proc page  @RecordCount int output,
@RecordCount int output,  @QueryStr nvarchar(100)='table1',--表名、视图名、查询语句
@QueryStr nvarchar(100)='table1',--表名、视图名、查询语句  @PageSize int=20, --每页的大小(行数)
@PageSize int=20, --每页的大小(行数)  @PageCurrent int=2, --要显示的页 从0开始
@PageCurrent int=2, --要显示的页 从0开始  @FdShow nvarchar (1000)='*', --要显示的字段列表
@FdShow nvarchar (1000)='*', --要显示的字段列表  @IdentityStr nvarchar (100)='id', --主键
@IdentityStr nvarchar (100)='id', --主键  @WhereStr nvarchar (200)='1=1',
@WhereStr nvarchar (200)='1=1',  @FdOrder nvarchar(100)='desc' --排序 只能取desc或者asc
@FdOrder nvarchar(100)='desc' --排序 只能取desc或者asc  as
as  declare
declare  @sql nvarchar(2000)
@sql nvarchar(2000)  set @sql = ''
set @sql = ''  if @WhereStr = ''
if @WhereStr = ''  set @WhereStr = '1=1'
set @WhereStr = '1=1' 
 if @PageCurrent = 0 begin
if @PageCurrent = 0 begin  set @sql = 'select top ' + cast(@PageSize as nvarchar(3)) + ' ' + @FdShow + ' from ' + @QueryStr + ' where ' + @WhereStr + ' order by ' + @IdentityStr + ' ' + @FdOrder
set @sql = 'select top ' + cast(@PageSize as nvarchar(3)) + ' ' + @FdShow + ' from ' + @QueryStr + ' where ' + @WhereStr + ' order by ' + @IdentityStr + ' ' + @FdOrder  end
end 
 else begin
else begin  if upper(@FdOrder) = 'DESC' begin
if upper(@FdOrder) = 'DESC' begin  set @sql = 'select top ' + cast(@PageSize as nvarchar(3)) + ' ' + @FdShow + ' from ' + @QueryStr + ' where ' + @WhereStr + ' and ' + @IdentityStr + '< ( select min(' + @IdentityStr + ') from (select top ' + cast(@PageSize*@PageCurrent as nvarchar(10)) + ' ' + @IdentityStr + ' from ' + @QueryStr + ' where ' + @WhereStr + ' order by ' + @IdentityStr + ' desc) as t) order by ' + @IdentityStr + ' desc'
set @sql = 'select top ' + cast(@PageSize as nvarchar(3)) + ' ' + @FdShow + ' from ' + @QueryStr + ' where ' + @WhereStr + ' and ' + @IdentityStr + '< ( select min(' + @IdentityStr + ') from (select top ' + cast(@PageSize*@PageCurrent as nvarchar(10)) + ' ' + @IdentityStr + ' from ' + @QueryStr + ' where ' + @WhereStr + ' order by ' + @IdentityStr + ' desc) as t) order by ' + @IdentityStr + ' desc'  end
end  else begin
else begin  set @sql = 'select top ' + cast(@PageSize as nvarchar(3)) + ' ' + @FdShow + ' from ' + @QueryStr + ' where ' + @WhereStr + ' and ' + @IdentityStr + '> ( select max(' + @IdentityStr + ') from (select top ' + cast(@PageSize*@PageCurrent as nvarchar(10)) + ' ' + @IdentityStr + ' from ' + @QueryStr + ' where ' + @WhereStr + ' order by ' + @IdentityStr + ' asc) as t) order by ' + @IdentityStr + ' asc'
set @sql = 'select top ' + cast(@PageSize as nvarchar(3)) + ' ' + @FdShow + ' from ' + @QueryStr + ' where ' + @WhereStr + ' and ' + @IdentityStr + '> ( select max(' + @IdentityStr + ') from (select top ' + cast(@PageSize*@PageCurrent as nvarchar(10)) + ' ' + @IdentityStr + ' from ' + @QueryStr + ' where ' + @WhereStr + ' order by ' + @IdentityStr + ' asc) as t) order by ' + @IdentityStr + ' asc'  end
end  end
end  --print @sql
--print @sql  execute(@sql)
execute(@sql) 

 if(@RecordCount is null or @RecordCount<=0)begin
if(@RecordCount is null or @RecordCount<=0)begin  declare @tsql nvarchar(200)
declare @tsql nvarchar(200)  set @tsql=N'select @RecordCount = count(*) from ' + @QueryStr + ' where ' + @WhereStr
set @tsql=N'select @RecordCount = count(*) from ' + @QueryStr + ' where ' + @WhereStr  exec sp_executesql @tsql,N'@RecordCount int output',@RecordCount output
exec sp_executesql @tsql,N'@RecordCount int output',@RecordCount output  select @Recordcount
select @Recordcount  end
end  GO
GO 

 
   .., 发表于2005-08-15 3:27 AM  IP: 61.186.252.*
.., 发表于2005-08-15 3:27 AM  IP: 61.186.252.* 愚以为前两种方法只对主键字段的排序有效。
愚以为前两种方法只对主键字段的排序有效。  ID NAME TYPEID
ID NAME TYPEID  1 aaa 1
1 aaa 1  2 bbb 2
2 bbb 2  3 ccc 3
3 ccc 3  4 ddd 3
4 ddd 3  5 eee 4
5 eee 4  6 fff 5
6 fff 5 
 例如有如上6条数据,ID为主键,TYPEID为外部键(索引)。
例如有如上6条数据,ID为主键,TYPEID为外部键(索引)。  如果使用ID排序,则可得正确结果。
如果使用ID排序,则可得正确结果。  但是如果使用TYPEID排序的话,每页显示3条数据,要显示第2页。则两种方法都只能显示2条记录,而实际应该是3条。
但是如果使用TYPEID排序的话,每页显示3条数据,要显示第2页。则两种方法都只能显示2条记录,而实际应该是3条。 
 第3种方法,由于在下对sql server的cursor不熟悉,所以不清楚结果。
第3种方法,由于在下对sql server的cursor不熟悉,所以不清楚结果。
 
   cnatang 发表于2005-09-13 3:04 PM  IP: 211.100.21.*
cnatang 发表于2005-09-13 3:04 PM  IP: 211.100.21.* 是啊。要实现一个完美的分页好象不可能??
是啊。要实现一个完美的分页好象不可能??  用方法2 ,我现在就碰到了 order by 非主键里的问题!
用方法2 ,我现在就碰到了 order by 非主键里的问题!  搞了一晚上,始终没有搞掂。楼主有什么好的解决办法?
搞了一晚上,始终没有搞掂。楼主有什么好的解决办法?
 
   zxub 发表于2005-10-13 10:21 PM  IP: 211.100.21.*
zxub 发表于2005-10-13 10:21 PM  IP: 211.100.21.* order by非主键的话,就用主键字段+排序字段,我就不信不能排,我做C#分页插件的时候就是这么做的,没问题的。
  order by非主键的话,就用主键字段+排序字段,我就不信不能排,我做C#分页插件的时候就是这么做的,没问题的。
 
   网教中国 发表于2005-12-08 10:09 AM  IP: 222.79.23.*
网教中国 发表于2005-12-08 10:09 AM  IP: 222.79.23.* 不错
不错

 
   oracle 发表于2006-01-05 10:31 AM  IP: 61.154.121.*
oracle 发表于2006-01-05 10:31 AM  IP: 61.154.121.* 都不好,大多数情况下不会用主键来排序,再说拼接sql这样索引就失效了,可能从效率最高掉到效率最低
都不好,大多数情况下不会用主键来排序,再说拼接sql这样索引就失效了,可能从效率最高掉到效率最低posted on 2006-01-15 10:24 Royman.Chen 阅读(609) 评论(1) 收藏 举报
 
                    
                     
                    
                 
                    
                 
 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号