CREATEPROCEDURE dbo.GetPageRecord ( @tblName varchar(255), -- 表名 @fldlist varchar(1000)='*', @fldName varchar(255), --排序字段 @KeyField varchar(255), --主键 @PageSize int=10, -- 页尺寸 @PageIndex int=1, -- 页码 @IsCount bit=0, -- 返回记录总数, 非 0 值则返回 @OrderType bit=1, -- 设置排序类型, 非 0 值则降序 @strWhere varchar(4000) =''-- 查询条件 (注意: 不要加 where) ) AS SET NOCOUNT ON DECLARE @PageLowerBound int DECLARE @PageUpperBound int -- Set the page bounds SET @PageLowerBound = @PageSize * @PageIndex SET @PageUpperBound = @PageLowerBound + @PageSize +1 -- Create a temp table to store the select results createtable #temp ( RecNo intIDENTITY (1, 1) NOTNULL, oldid int ) --generate record Declare @Sqlstr varchar(6000) set @sqlstr='select '+@Keyfield+' from '+@tblname if(@strWhere<>'') begin set @Sqlstr=@sqlstr+' where ('+@strWhere+')' end set @sqlstr=@sqlstr+' order by '+@fldName if(@ordertype=0) begin set @sqlstr=@sqlstr+' asc' end else begin set @sqlstr=@sqlstr+' desc' end set @sqlstr='insert into #temp (oldid) '+@sqlstr execute(@sqlstr) set @sqlstr='SELECT '+@fldList+' FROM '+@tblname+' TableA (nolock), #temp T WHERE T.oldid = TableA.'+@keyfield+' AND T.RecNo > '+cast(@PageLowerBound asvarchar)+' AND T.RecNo < '+cast(@PageUpperBound asvarchar)+' ORDER BY T.RecNo' execute(@sqlstr) GO
selecttop10*from (selecttop100*from tblproducts where name like'%mp3%'orderby id desc) as a orderby id desc
请相信你的眼睛,上面的语句确实能执行,可能你曾经试过执行类似的语句但并未成功,那是因为你没有将来源结果集指定别名 第二个秘密是一个规则: 如果你想用select top 20*4的方式在SQL中取前80条记录,你会失败,因为TOP子句有一个限制,就是TOP num中的num不能是一个计算值或表达式而必须是一个既定的常量 第三个秘密足够重大,我想,应该很少有人发现它,否则的话,很多问题便会变得简单起来,简要的说,它就是:SQL允许你用EXECUTE执行一个变量中定义的SQL语句,并且允许你在被执行的SQL语句中,再次嵌套入一个变量定义的语句,并且再次在其中用EXECUTE执行它,如果语言不足以证明,那么下面的代码将证明这是行得通并且是很好的
declare @sqlstr varchar(3000) set @sqlstr='declare @subsqlstr varchar(1000);' set @sqlstr=@sqlstr+'set @subsqlstr=''select * from tblproducts'';' set @sqlstr=@sqlstr+'execute (@subsqlstr)' execute(@sqlstr)
最后,我用上面的方法写了两种SQL通用分页存储过程: 它们具有以下特点1,支持字段集合选择,2支持任意字段排序, 上面的图,我们以最终结果集倒序为例,第一种方案,我们先取集集合OB,这可以用一个使用SELECT TOP 并使用升级排列的语句完成 然后对OB结果集进行倒序排序,再用"SELECT TOP 每页记录数"倒序 的方式取得目标集合AB,下面是存储过程
createPROCEDURE dbo.GetPagingData ( @tablename varchar(100),--表名或视图表 @fieldlist varchar(4000)='*',--欲选择字段列表 @orderfield varchar(100),--排序字段 @keyfield varchar(100),--主键 @pageindex int,--页号,从0开始 @pagesize int=20,--页尺寸 @strwhere varchar(4000),--条件 @ordertype bit=1--排序,1,降序,0,升序 ) AS /**//* 名称:GetPagingRecord 作用:按任意字段进行排序分页 作者:菩提树(MARK MA) 时间:2004-12-14 声明:此代码你可以无偿使用及转载,但在转载时,请勿移称本文字声明 */ SET NOCOUNT ON declare @sqlstr varchar(6000) --处理SQL中危险字符,并且将条件处理成易嵌入的形式 set @sqlstr='declare @Rcount int;' set @sqlstr=@sqlstr+'set @rcount=(select count('+@keyfield+') from '+@tablename+' where '+@strWhere+');' set @strwhere=replace(@strwhere,'''','''''') set @strwhere=replace(@strwhere,'--','') set @strwhere=replace(@strwhere,';','') set @sqlstr=@sqlstr+'declare @Rnum int;' set @sqlstr=@sqlstr+'set @rnum=@rcount-'+cast(@pagesize asvarchar)+'*'+cast(@pageindex asvarchar)+';' set @sqlstr=@sqlstr+'declare @sqlstr varchar(6000);' if @ordertype=1 begin set @sqlstr=@sqlstr+'set @sqlstr=''select top '+cast(@Pagesize asvarchar)+''+@fieldlist+' from (select top 100 percent * from (select top ''+cast(@rnum as varchar)+'' * from '+@tablename+' where '+@strwhere+' order by '+@orderfield+' asc) as b order by paymoney desc) as a order by '+@orderfield+' desc '';' end else begin set @sqlstr=@sqlstr+'set @sqlstr=''select top '+cast(@Pagesize asvarchar)+''+@fieldlist+' from (select top 100 percent * from (select top ''+cast(@rnum as varchar)+'' * from '+@tablename+' where '+@strwhere+' order by '+@orderfield+' desc) as b order by paymoney asc) as a order by '+@orderfield+' asc '';' end set @sqlstr=@sqlstr+'if @Rcount>0 begin execute(@sqlstr) end' --print @sqlstr execute(@sqlstr)
在上面的代码中,还处理了没有符合条件结果的情况 第二种方案的思想是这样的,先用倒序的SELECT TOP (页序号+1)*页尺寸的方法取得AE结果集,再从AE结果集中用NOT IN 的方法排除掉用SELECT TOP 页序号*页尺寸的方法取得的结果集,最后,对目标结果集执行倒序,下面是实现的代码
createPROCEDURE dbo.GetPagingRecord ( @tablename varchar(100),--表名或视图表 @fieldlist varchar(4000)='*',--欲选择字段列表 @orderfield varchar(100),--排序字段 @keyfield varchar(100),--主键 @pageindex int,--页号,从0开始 @pagesize int=20,--页尺寸 @strwhere varchar(4000),--条件 @ordertype bit=1--排序,1,降序,0,升序 ) AS /**//* 名称:GetPagingRecord 作用:按任意字段进行排序分页 作者:菩提树(MARK MA) 时间:2004-12-14 声明:此代码你可以无偿使用及转载,但在转载时,请勿移称本文字声明 */ SET NOCOUNT ON declare @sqlstr varchar(6000) --处理SQL中危险字符,并且将条件处理成易嵌入的形式 set @strwhere=replace(@strwhere,'''','''''') set @strwhere=replace(@strwhere,'--','') set @strwhere=replace(@strwhere,';','') set @sqlstr='declare @CurPageNum int;' set @sqlstr=@sqlstr+'declare @nextpagenum int;' set @sqlstr=@sqlstr+'set @curpagenum='+cast(@PageIndex asvarchar)+'*'+cast(@Pagesize asvarchar)+';' set @sqlstr=@sqlstr+'set @nextpagenum='+cast(@PageIndex+1asvarchar)+'*'+cast(@Pagesize asvarchar)+';' set @sqlstr=@sqlstr+'declare @sqlstr varchar(6000);' if @ordertype=1 begin set @sqlstr=@sqlstr+'set @sqlstr=''select '+@fieldlist+' from ( select top ''+cast(@nextpagenum as varchar)+'' * from '+@tablename+' where '+@strwhere+' order by '+@orderfield+' desc ) as a where '+@keyfield+' not in ( select top ''+cast(@curpagenum as varchar)+'''+@keyfield+' from '+@tablename+' where '+@strwhere+' order by '+@orderfield+' desc) order by '+@orderfield+' desc'';' end else begin set @sqlstr=@sqlstr+'set @sqlstr=''select '+@fieldlist+' from ( select top ''+cast(@nextpagenum as varchar)+'' * from '+@tablename+' where '+@strwhere+' order by '+@orderfield+' asc ) as a where '+@keyfield+' not in ( select top ''+cast(@curpagenum as varchar)+'''+@keyfield+' from '+@tablename+' where '+@strwhere+' order by '+@orderfield+' asc) order by '+@orderfield+' asc'';' end set @sqlstr=@sqlstr+'execute( @sqlstr)' --print @sqlstr execute(@sqlstr)