通用数据分页存储过程

目前基于Sql语句的分页算法已经比较普及,但查询最后N页的时候速度普遍缓慢.支持MS SqlServer.


---------------------------------------
--名称:fn_IsNull
--描述:参数空值判断,可包括:字符串,整型,VARBINARY等是否为空的判断
--输入:参数
--输出:无
--返回:是否为空标志,输出类型为bit,0表示不为空,1表示为空
---------------------------------------
CREATE FUNCTION [dbo].[fn_IsNull]
(
@psStr NVARCHAR(1000) --字符串
)
RETURNS BIT
AS
BEGIN
DECLARE @tFlag bit
IF (@psStr IS NULL) OR (LEN(@psStr)=0)
SET @tFlag=1
ELSE
SET @tFlag=0
RETURN @tFlag
END




-------------------------------------
--
-- 数据通用分页
--
-------------------------------------
CREATE PROCEDURE dbo.sp_General_Pagination
@psTblName VARCHAR(1000) = NULL, -- 设置表名
@psStrGetFields VARCHAR(200) = '*' , -- 设置需要返回的列名
@psFidName VARCHAR(255) = NULL, -- 设置排序的字段名
@psPageSize INT = 10, -- 设置分页尺寸,必须大于0
@psPageIndex INT = 1, -- 设置分页码,必须大于0
@psOrderType BIT = 0, -- 设置排序类型, 非0非空值则降序
@psStrWhere VARCHAR(2500) = NULL, -- 设置查询条件(注:不要加WHERE)
@rsPageCount INT = 0 OUTPUT, -- 输出页数
@rsRecordCount INT = 0 OUTPUT -- 输出记录总数
AS
BEGIN
SET NOCOUNT ON
-- 参数合法性检查
IF (
(dbo.fn_IsNull(@psTblName)= 1) -- 判断表名为空时返回
OR (dbo.fn_IsNull(@psFidName) = 1) -- 判断排序字段为空时返回
OR (dbo.fn_IsNull(@psPageIndex) = 1) -- 判断分页尺寸为空时返回
OR (dbo.fn_IsNull(@psPageSize) = 1) -- 判断分页码为空时返回
OR (@psPageIndex <= 0) -- 如果分页尺寸小于等于0,返回
OR (@psPageSize <= 0) -- 如果分页码小于等于0,返回
)
BEGIN
RETURN 0
END
-- 判断返回列名字段为空时设置为'*'
IF (dbo.fn_IsNull(@psStrGetFields)= 1)
BEGIN
SET @psStrGetFields = '*'
END
IF (dbo.fn_IsNull(@psStrWhere)= 1)
BEGIN
SET @psStrWhere = ''
END

-- 定义参数
DECLARE @strNSQL NVARCHAR(4000) -- 主语句
DECLARE @strSQL VARCHAR(8000) -- 主语句
DECLARE @strTmp VARCHAR(20) -- 临时变量
DECLARE @strParams VARCHAR(500) -- 参数值
DECLARE @strOrder VARCHAR(200) -- 排序类型
DECLARE @strPageSize VARCHAR(10) --页大小
DECLARE @strTopPageSize VARCHAR(10) --转换后的页大小
DECLARE @strMaxTmp VARCHAR(8000)
--参数初始化
SET @strNSQL=''
SET @strSQL=''
SET @strTmp=''
SET @strParams=''
SET @strOrder=''
SET @strPageSize=''
SET @strTopPageSize=''
SET @strMaxTmp=''
SET @strMaxTmp='' --必要

----- END

-- 计算总记录数(OUTPUT参数)
IF (dbo.fn_IsNull(@psStrWhere)= 0) -- 判断是否有条件语句
BEGIN
SET @strNSQL = 'SELECT @rsRecordCount = COUNT(1)'+CHAR(10)+' FROM ' + @psTblName
+CHAR(10)+ ' WHERE ' + @psStrWhere+CHAR(10)
END
ELSE
BEGIN
SET @strNSQL = 'SELECT @rsRecordCount = COUNT(1)'+CHAR(10)+' FROM ' + @psTblName+CHAR(10)
END

--PRINT @strNSQL

-- 执行SQL语句,求出总记录数
EXEC sp_executesql @strNSQL, N'@rsRecordCount INT OUTPUT',@rsRecordCount OUTPUT
IF @@ERROR <> 0
BEGIN
RETURN 0
END
-- 计算总页数(OUTPUT参数)
SET @rsPageCount =CEILING( @rsRecordCount*1.0 / @psPageSize)

-- 如果总页数为0,直接返回
IF (@rsRecordCount = 0)
BEGIN
EXEC ('SELECT ' + @psStrGetFields + ' FROM '+ @psTblName + ' WHERE 1<>1')
IF @@ERROR <> 0
BEGIN
RETURN 0
END
ELSE
BEGIN
RETURN 1
END
END

--如果分页码大于总页数则把分页码置为总页数,表示取最后一页
IF (@psPageIndex>@rsPageCount) AND (@rsPageCount>0)
BEGIN
SET @psPageIndex=@rsPageCount
END
--如果页大小超过总页数,自动纠正
IF(@psPageSize>@rsRecordCount)
BEGIN
SET @psPageSize=@rsRecordCount
END

-- 把页大小转换为字符串
SET @strPageSize= CONVERT(varchar(10),@psPageSize)
SET @strTopPageSize=@strPageSize

DECLARE @tReverseFlag INT
--如果当前页不是第一页,且大等于总页数的一半,才需要倒过来处理
IF(@psPageIndex>1 AND @psPageIndex>@rsPageCount*1.0/2)
BEGIN
SET @tReverseFlag=1
SET @psPageIndex=@rsPageCount-@psPageIndex+1
END
ELSE
BEGIN
SET @tReverseFlag=0
END

--保证@psOrderType有确定的值好作位运算
IF(dbo.fn_IsNull(@psOrderType)= 1)
BEGIN
SET @psOrderType=0
END
IF(@psOrderType!=0)
BEGIN
SET @psOrderType=1
END
--根据位运算结果来判断是该升序还是降序
IF (@psOrderType ^ @tReverseFlag=1)
BEGIN --需要降序处理
SET @strTmp = ' < '
SET @strParams = 'MIN'
SET @strOrder = ' ORDER BY ' + @psFidName + ' DESC'
END
ELSE
BEGIN --需要升序处理
SET @strTmp = ' > '
SET @strParams = 'MAX'
SET @strOrder = ' ORDER BY ' + @psFidName + ' ASC'
END

-- 主语句
IF @psPageIndex = 1 -- 如果是第一页就加速执行
BEGIN
--如果被转换且未被整除
IF(@tReverseFlag=1 AND @rsRecordCount % @psPageSize<>0)
BEGIN
SET @strTopPageSize=CONVERT(VARCHAR(10),@rsRecordCount % @psPageSize)
END

-- 判断是否有条件语句
IF (dbo.fn_IsNull(@psStrWhere)=0)
BEGIN
SET @strSQL = 'SELECT TOP ' + @strTopPageSize + ' ' + @psStrGetFields
+ CHAR(10) + ' FROM ' + @psTblName
+ CHAR(10) + ' WHERE '
END
ELSE
BEGIN
SET @strSQL = 'SELECT TOP ' + @strTopPageSize + ' ' + @psStrGetFields
+ CHAR(10)+' FROM ' + @psTblName
END

END
ELSE -- 否则不是第一页就执行以下步骤
BEGIN
SET @strTopPageSize=CONVERT(VARCHAR(10),(@psPageIndex-1)*@psPageSize)
--如果被转换且未被整除
IF(@tReverseFlag=1) AND ( @rsRecordCount % @psPageSize<>0)
BEGIN --
SET @strTopPageSize=CONVERT(VARCHAR(10),(@psPageIndex-1)*@psPageSize-(@psPageSize-@rsRecordCount % @psPageSize))
END

SET @strMaxTmp = 'DECLARE @strTmp VARCHAR(500) '+CHAR(10)
+ 'SELECT @strTmp = ' + @strParams + '(' + @psFidName + ') FROM (SELECT TOP '
+ @strTopPageSize+' ' + @psFidName + ' FROM ' + @psTblName

-- 判断是否有条件语句

IF (dbo.fn_IsNull(@psStrWhere)=0) -- 如果有条件语句就执行这一步
BEGIN

SET @strMaxTmp = @strMaxTmp + ' WHERE ' + @psStrWhere + ' ' + @strOrder + ') AS tblTmp '+CHAR(10)
SET @strSQL= 'SELECT TOP ' + @strPageSize + ' ' + @psStrGetFields
+ CHAR(10) +' FROM ' + @psTblName
+ CHAR(10) +' WHERE ' + @psFidName + '' + @strTmp + '@strTmp AND '
END
ELSE -- 如果没有条件语句就执行这一步
BEGIN

SET @strMaxTmp = @strMaxTmp + @strOrder + ') AS tblTmp '+CHAR(10)
SET @strSQL= 'SELECT TOP ' + @strPageSize + ' ' + @psStrGetFields
+ CHAR(10) +' FROM ' + @psTblName
+ CHAR(10) +' WHERE ' + @psFidName + '' + @strTmp + '@strTmp '
END

END

-------------
SET @strSQL=@strSQL +@psStrWhere+ CHAR(10)+@strOrder
--如果已经进行转换,结果的排序还要倒换过来
IF(@tReverseFlag=1)
BEGIN
SET @strSQL='SELECT '+@psStrGetFields+',IDENTITY(int,1,1) AS OrderField INTO #tmptbl FROM ('+@strSQL + ') AS tbl800'+ CHAR(10)
SET @strSQL=@strSQL+'SELECT '+@psStrGetFields+' FROM #tmptbl ORDER BY OrderField DESC;DROP TABLE #tmptbl;'
END

-- 执行SQL语句,求出数据集
--PRINT @strMaxTmp+@strSQL
EXEC (@strMaxTmp+@strSQL)
IF @@ERROR <> 0
BEGIN
RETURN 0
END
ELSE
BEGIN
RETURN 1
END

END


GO


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值