第一种方案,我们先取集集合OB,这可以用一个使用SELECT TOP 并使用升级排列的语句完成

然后对OB结果集进行倒序排序,再用"SELECT TOP 每页记录数"倒序 的方式取得目标集合AB,下面是存储过程

create PROCEDURE 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

BEGIN

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 as varchar)+'*'+cast(@pageindex as varchar)+';'

set @sqlstr=@sqlstr+'declare @sqlstr varchar(6000);'

if @ordertype=1

begin

set @sqlstr=@sqlstr+'set @sqlstr=''select top '+cast(@Pagesize as varchar)+' '+@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 as varchar)+' '+@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)

END

在上面的代码中,还处理了没有符合条件结果的情况

第二种方案的思想是这样的,先用倒序的SELECT TOP (页序号+1)*页尺寸的方法取得AE结果集,再从AE结果集中用NOT IN 的方法排除掉用SELECT TOP 页序号*页尺寸的方法取得的结果集,最后,对目标结果集执行倒序,下面是实现的代码

View Code

create PROCEDURE 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

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 as varchar)+'*'+cast(@Pagesize as varchar)+';'

set @sqlstr=@sqlstr+'set @nextpagenum='+cast(@PageIndex+1 as varchar)+'*'+cast(@Pagesize as varchar)+';'

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)

需要注意的是,如果要避免SQL注入式攻击,请注意处理像分号,双减号,单引号这些在SQL中有特殊含义的字符

至于上面两个存储过程哪个性能更好,那就取决于是对一个倒序的结果集再进入一次反序排列好呢,还是用NOT IN从一个大的结果集移除一个小的结果集好

第三种方案

成熟的分类过程

View Code

create PROCEDURE CMS_SearchGetDataByPage
@tblName varchar(255), -- 表名
@fldNames varchar(1000), -- 选择的字段列表以,分隔
@selectOrderFldName varchar(500), -- 排序字段以,分隔(不能含keyFldName指定的字段,可为空)
@orderFldDesc varchar(500), -- 排序字段及排序方向,如addDate desc,id desc(排序字段需通过selectOrderFldName指定,可为空)
@keyFldName varchar(255), -- 主键字段
@PageSize int = 10, -- 页尺寸
@PageIndex int = 1, -- 页码
@strWhere varchar(1000) = '' -- 查询条件(注意: 不要加where)
AS
declare @strWhereA varchar(1200) -- 临时变量,给sqlwhere加where
declare @strOrderA varchar(2000) -- 第一次排序类型
declare @strOrderB varchar(2000) -- 第二次排序类型
declare @strSqlA varchar(4000) -- 第一次选出
declare @strSqlB varchar(8000) -- 第二次选出
declare @strSQL varchar(8000) -- 最后选出
/* 条件*/
if @strWhere != ''
set @strWhereA = ' where ' + @strWhere
else
set @strWhereA = ''

/* 选择字段列表*/
if @fldNames is null or rtrim(@fldNames) = ''
set @fldNames = '*'

/* 排序字段列表*/
if not(@selectOrderFldName is null or rtrim(@selectOrderFldName) = '')
if rtrim(@selectOrderFldName) = 'id'
set @selectOrderFldName = ''
else
set @selectOrderFldName = ',' + @selectOrderFldName

/* 构建order,按指定方式排序*/
if @orderFldDesc is null or rtrim(@orderFldDesc) = ''
set @orderFldDesc = ' order by id desc'
else
set @orderFldDesc = ' order by ' + @orderFldDesc
set @strOrderA = UPPER(@orderFldDesc)
set @strOrderB = replace(@strOrderA,'DESC','DESC1')
set @strOrderB = replace(@strOrderB,'ASC','DESC')
set @strOrderB = replace(@strOrderB,'DESC1','ASC')

/* 第一页*/
if @PageIndex = 1
set @strSQL = 'select top ' + str(@PageSize) + ' ' + @fldNames + ' from [' + @tblName + '] with(nolock)' + @strWhereA + ' ' + @strOrderA
else
begin
--取得总记录数
declare @sql nvarchar(500)
declare @maxCount int
declare @maxPage int
declare @tempRowCount int
set @sql ='select @maxCount = count('+@keyFldName+') from [' + @tblName + ']' + @strWhereA
exec sp_executesql @sql,N'@maxCount int output',@maxCount output
set @maxPage = @maxCount / @PageSize
if(@maxCount % @PageSize > 0)
set @maxPage = @maxPage + 1
/* 最后一页*/
if @PageIndex >= @maxPage
begin
set @PageIndex = @maxPage
set @strSqlA = char(13) + '(select top '+str(@maxCount % @PageSize)+' ' + @keyFldName + @selectOrderFldName + ' from [' + @tblName + '] as a with(nolock) ' + @strWhereA + @strOrderB + ' )' + char(13)
set @strSqlB = char(13) + '(select ' + @keyFldName +' from ' + @strSqlA + ' as b )' + char(13)
set @strSQL = 'select ' + @fldNames + ' from [' + @tblName + '] where ([' + @keyFldName + '] in '+@strSqlB+')' + @strOrderA + char(13)
end
else
begin
/* 不是第一页,也不是最后一页*/
if(@PageIndex <= @maxPage / 2)
begin
--前半数的页
set @tempRowCount = @PageIndex * @PageSize
/* 构建SQL,本分页算法的目的是为了实现高效的非主键排序的分页。by tony */
/* 1、先按指定字段+主键字段按降序选出perPage*pageNum条记录*/
set @strSqlA = char(13) + '(select top '+str(@tempRowCount)+' ' + @keyFldName + @selectOrderFldName + ' from [' + @tblName + '] as a with(nolock) ' + @strWhereA + @strOrderA + ' )' + char(13)
/* 2、再从选出的记录中按升序选出perPage条记录*/
set @strSqlB = char(13) + '(select top '+str(@PageSize)+' ' + @keyFldName + ' from ' + @strSqlA + ' as b ' + @strOrderB + ' )' + char(13)
/* 3、从数据库中选出主键在第二次选出的记录中的记录,按降序排列,分页完成*/
set @strSQL = 'select ' + @fldNames + ' from [' + @tblName + '] where ([' + @keyFldName + '] in '+@strSqlB+')' + @strOrderA
end
else
begin
--后半数的页
set @tempRowCount = @maxCount - (@PageIndex -1) * @PageSize
/* 构建SQL,本分页算法的目的是为了实现高效的非主键排序的分页。by tony */
/* 1、先按指定字段+主键字段按降序选出perPage*pageNum条记录*/
set @strSqlA = char(13) + '(select top '+str(@tempRowCount)+' ' + @keyFldName + @selectOrderFldName + ' from [' + @tblName + '] as a with(nolock) ' + @strWhereA + @strOrderB + ' )' + char(13)
/* 2、再从选出的记录中按升序选出perPage条记录*/
set @strSqlB = char(13) + '(select top '+str(@PageSize)+' ' + @keyFldName + ' from ' + @strSqlA + ' as b ' + @strOrderA + ' )' + char(13)
/* 3、从数据库中选出主键在第二次选出的记录中的记录,按降序排列,分页完成*/
set @strSQL = 'select ' + @fldNames + ' from [' + @tblName + '] where ([' + @keyFldName + '] in '+@strSqlB+')' + @strOrderA
end
end
end

set nocount on

/*print @strSQL*/ --显示SQL
exec (@strSQL)
set nocount off
RETURN

第四种方案

View Code

CREATE PROC SP_PageList
@tbname sysname, --要分页显示的表名
@FieldKey sysname, --用于定位记录的主键(惟一键)字段,只能是单个字段
@PageCurrent int=1, --要显示的页码
@PageSize int=10, --每页的大小(记录数)
@FieldShow nvarchar(1000)='', --以逗号分隔的要显示的字段列表,如果不指定,则显示所有字段
@FieldOrder nvarchar(1000)='', --以逗号分隔的排序字段列表,可以指定在字段后面指定DESC/ASC
--用于指定排序顺序
@Where nvarchar(1000)='', --查询条件
@RecordCount int OUTPUT, --总记录数
@PageCount int OUTPUT --总页数
AS
DECLARE @sql nvarchar(4000)
SET NOCOUNT ON
--检查对象是否有效
IF OBJECT_ID(@tbname) IS NULL
BEGIN
RAISERROR(N'对象"%s"不存在',1,16,@tbname)
RETURN
END
IF OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsTable')=0
AND OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsView')=0
AND OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsTableFunction')=0
BEGIN
RAISERROR(N'"%s"不是表、视图或者表值函数',1,16,@tbname)
RETURN
END

--分页字段检查
IF ISNULL(@FieldKey,N'')=''
BEGIN
RAISERROR(N'分页处理需要主键(或者惟一键)',1,16)
RETURN
END

--其他参数检查及规范
IF ISNULL(@PageCurrent,0)<1 SET @PageCurrent=1
IF ISNULL(@PageSize,0)<1 SET @PageSize=10
IF ISNULL(@FieldShow,N'')=N'' SET @FieldShow=N'*'
IF ISNULL(@FieldOrder,N'')=N''
SET @FieldOrder=N''
ELSE
SET @FieldOrder=N'ORDER BY '+LTRIM(@FieldOrder)
IF ISNULL(@Where,N'')=N''
SET @Where=N''
ELSE
SET @Where=N'WHERE ('+@Where+N')'

--如果@PageCount为NULL值,则计算总页数(这样设计可以只在第一次计算总页数,以后调用时,把总页数传回给存储过程,避免再次计算总页数,对于不想计算总页数的处理而言,可以给@PageCount赋值)
IF @PageCount IS NULL
BEGIN
SET @sql=N'SELECT @PageCount=COUNT(*)'
+N' FROM '+@tbname
+N' '+@Where
EXEC sp_executesql @sql,N'@PageCount int OUTPUT',@PageCount OUTPUT
SET @RecordCount = @PageCount
SET @PageCount=(@PageCount+@PageSize-1)/@PageSize
END

--计算分页显示的TOPN值
DECLARE @TopN varchar(20),@TopN1 varchar(20)
SELECT @TopN=@PageSize,
@TopN1=@PageCurrent*@PageSize

--第一页直接显示
IF @PageCurrent=1
EXEC(N'SELECT TOP '+@TopN
+N' '+@FieldShow
+N' FROM '+@tbname
+N' '+@Where
+N' '+@FieldOrder)
ELSE
BEGIN
SELECT @PageCurrent=@TopN1,
@sql=N'SELECT @n=@n-1,@s=CASE WHEN @n<'+@TopN
+N' THEN @s+N'',''+QUOTENAME(RTRIM(CAST('+@FieldKey
+N' as varchar(8000))),N'''''''') ELSE N'''' END FROM '+@tbname
+N' '+@Where
+N' '+@FieldOrder
SET ROWCOUNT @PageCurrent
EXEC sp_executesql @sql,
N'@n int,@s nvarchar(4000) OUTPUT',
@PageCurrent,@sql OUTPUT
SET ROWCOUNT 0
IF @sql=N''
EXEC(N'SELECT TOP 0'
+N' '+@FieldShow
+N' FROM '+@tbname)
ELSE
BEGIN
SET @sql=STUFF(@sql,1,1,N'')
--执行查询
EXEC(N'SELECT TOP '+@TopN
+N' '+@FieldShow
+N' FROM '+@tbname
+N' WHERE '+@FieldKey
+N' IN('+@sql
+N') '+@FieldOrder)
END
END
GO

转载于:https://www.cnblogs.com/samsonhuang/articles/2092839.html

[ MSSQL ]分页排序存储过程相关推荐

  1. SqlServer分页排序存储过程 V1.0

    set ANSI_NULLS ON  set QUOTED_IDENTIFIER ON  GO  /*  分页排序存储过程 V1.0  */ ALTER procedure [dbo].[sp_Key ...

  2. Oracle大数据量分页通用存储过程

    type refCursorType is REF CURSOR;  --游标类型定义,用于返回数据集 /*********************************************** ...

  3. SQL SERVER两种分页的存储过程介绍

    由于现在很多的企业招聘的笔试都会让来招聘的写一个分页的存储过程,有的企业甚至要求应聘者用两种方式实现分页,如果没有在实际项目中使用过分页,那么很多的应聘者都会出现一定的问题,下面介绍两种分页的方法. ...

  4. php+mssql 分页,一个PHP+MSSQL分页的例子

    一个PHP+MSSQL分页的例子 更新时间:2006年10月09日 00:00:00   作者: require "config.php"; dl("extensions ...

  5. jooq 分页排序_将jOOQ与Spring结合使用:排序和分页

    jooq 分页排序 JOOQ是一个库,可以帮助我们控制SQL. 它可以从我们的数据库生成代码,并允许我们使用其流畅的API来构建类型安全的数据库查询. 本教程前面的部分向我们介绍了如何配置应用程序的应 ...

  6. jpa 分页 排序 过滤_使用JPA标准@ViewScoped通过分页,过滤和排序进行Primefaces DataTable延迟加载...

    jpa 分页 排序 过滤 Primefaces数据表惰性分页有效,但是在Web上使用Criteria搜索完整示例后,我感到非常沮丧. 所以我混合了来自 http://stackoverflow.com ...

  7. MSSQLServer基础07(事务,存储过程,分页的存储过程,触发器)

    事务 事务:保证多个操作全部成功,否则全部失败,这处机制就是事务 思考:下了个订单,但是在保存详细信息时出错了,这样可以成功吗? 数据库中的事务:代码全都成功则提交,如果有某一条语句失败则回滚,整体失 ...

  8. Spring Boot 学习[四] web项目实战训练(增删改查,分页,排序)

    Spring boot非常适合Web应用程序开发.您可以轻松创建自包含的HTTP应用.web服务器采用嵌入式Tomcat,或者Jetty等. 几点说明: Spring boot开发web项目,通常打成 ...

  9. MybatisPlus 分页排序封装

    思路 采用 HandlerMethodArgumentResolver 预先对排序数据处理. 代码 MybatisPlusProperties @ConfigurationProperties(&qu ...

最新文章

  1. 算法导轮之B树的学习
  2. 洛谷 - P3246 [HNOI2016]序列(莫队+单调栈)
  3. 网信金融 与 金银猫合作
  4. C#令人迷惑的DateTime:世界标准时间还是本地时间?
  5. spring mvc框架请求注解解析,内部资源视图解析器
  6. nginx指定配置文件启动_NGINX安全加固手册
  7. 评价最高影片JAVAlibrary_视频 | 手游大神,动画导演,机圈新贵,极客怎么评价《愤怒的小鸟2》?...
  8. mysql key语句_mysql建表语句key的含义
  9. 【原创】笔记本键盘故障的心得一二
  10. arcgis js(二)显示三维地图
  11. 线性代数笔记33——基变换和图像压缩
  12. 解决No thread-bound request found: Are you referring to request attributes outside of an actual web...
  13. 【PhotoShop】用自己的照片做个好看的星空头像PS
  14. jenkins + jmeter +ant 发送邮件失败
  15. 计算机毕业设计Java星星电影购票网站(源码+系统+mysql数据库+lw文档
  16. Python项目之企业审批流绩效分析分析应用2
  17. excel按季度分类汇总_excel进行分类汇总的五种方法
  18. 杰力科创RGB低频加湿器芯片——DLT8W10SD
  19. JAVASCRIPT显示农历的日历
  20. extern “C“ 理解

热门文章

  1. Moses Staff攻陷以色列网络并加密数据,拒绝谈判
  2. Facebook 开源 Instagram 的Python 代码静态安全分析工具 Pysa
  3. python内置函数map/reduce/filter
  4. 一分钟教你学会配置eslint,还在为风格单双引号,对象末位逗号要不要,引用各种报错而烦恼?(建议收藏!详细中文注释)...
  5. 时隔5年 三星要重回苹果闪存零部件供应商名单了
  6. 进程VS线程---操作类型
  7. android与服务器交互总结(json,post,xUtils,Volley)
  8. android——根据MVC框架设计的结构
  9. VS2010整合NUnit进行单元测试
  10. Axis2创建WebService实例