(抓)2分法-通用存储过程分页(top max模式)版本(性能相对之前的not in版本极大提高)

2分法-通用存储过程分页(top max模式)版本(性能相对之前的not in版本极大提高)       
分类:            数据分页 2659人阅读 评论(9) 收藏 举报
-- /*-----存储过程 分页处理 SW 2005-03-28创建 -------*/
--
/*----- 对数据进行了2分处理使查询前半部分数据与查询后半部分数据性能相同 -------*/
--
/*-----存储过程 分页处理 2005-04-21修改 添加Distinct查询功能-------*/
--
/*-----存储过程 分页处理 2005-05-18修改 多字段排序规则问题-------*/
--
/*-----存储过程 分页处理 2005-06-15修改 多字段排序修改-------*/
--
/*-----存储过程 分页处理 2005-12-13修改 修改数据分页方式为top max模式 性能有极大提高-------*/
--
/*-----缺点:相对之前的not in版本主键只能是整型字段,如主键为GUID类型请使用not in 模式的版本-------*/
CREATE PROCEDURE dbo.proc_ListPageInt
(
@tblName      nvarchar ( 200 ),        -- --要显示的表或多个表的连接
@fldName      nvarchar ( 500 ) = ' * ' ,    -- --要显示的字段列表
@pageSize     int = 10 ,        -- --每页显示的记录个数
@page         int = 1 ,        -- --要显示那一页的记录
@pageCount     int = 1 output,            -- --查询结果分页后的总页数
@Counts     int = 1 output,                -- --查询到的记录数
@fldSort     nvarchar ( 200 ) = null ,    -- --排序字段列表或条件
@Sort         bit = 0 ,        -- --排序方法,0为升序,1为降序(如果是多字段排列Sort指代最后一个排序字段的排列顺序(最后一个排序字段不加排序标记)--程序传参如:' SortA Asc,SortB Desc,SortC ')
@strCondition     nvarchar ( 1000 ) = null ,    -- --查询条件,不需where
@ID         nvarchar ( 150 ),        -- --主表的主键
@Dist                  bit = 0            -- --是否添加查询字段的 DISTINCT 默认0不添加/1添加
)
AS
SET NOCOUNT ON
Declare @sqlTmp nvarchar ( 1000 )        -- --存放动态生成的SQL语句
Declare @strTmp nvarchar ( 1000 )        -- --存放取得查询结果总数的查询语句
Declare @strID      nvarchar ( 1000 )        -- --存放取得查询开头或结尾ID的查询语句

Declare @strSortType nvarchar ( 10 )    -- --数据排序规则A
Declare @strFSortType nvarchar ( 10 )    -- --数据排序规则B

Declare @SqlSelect nvarchar ( 50 )         -- --对含有DISTINCT的查询进行SQL构造
Declare @SqlCounts nvarchar ( 50 )          -- --对含有DISTINCT的总数查询进行SQL构造


if @Dist   = 0
begin
   
set @SqlSelect = ' select '
   
set @SqlCounts = ' Count(*) '
end
else
begin
   
set @SqlSelect = ' select distinct '
   
set @SqlCounts = ' Count(DISTINCT ' + @ID + ' ) '
end


if @Sort = 0
begin
   
set @strFSortType = ' ASC '
   
set @strSortType = ' DESC '
end
else
begin
   
set @strFSortType = ' DESC '
   
set @strSortType = ' ASC '
end



-- ------生成查询语句--------
--
此处@strTmp为取得查询结果数量的语句
if @strCondition is null or @strCondition = ''      -- 没有设置显示条件
begin
   
set @sqlTmp =   @fldName + ' From ' + @tblName
   
set @strTmp = @SqlSelect + ' @Counts= ' + @SqlCounts + ' FROM ' + @tblName
   
set @strID = ' From ' + @tblName
end
else
begin
   
set @sqlTmp = + @fldName + ' From ' + @tblName + ' where (1>0) ' + @strCondition
   
set @strTmp = @SqlSelect + ' @Counts= ' + @SqlCounts + ' FROM ' + @tblName + ' where (1>0) ' + @strCondition
   
set @strID = ' From ' + @tblName + ' where (1>0) ' + @strCondition
end

-- --取得查询结果总数量-----
exec sp_executesql @strTmp ,N ' @Counts int out ' , @Counts out
declare @tmpCounts int
if @Counts = 0
   
set @tmpCounts = 1
else
   
set @tmpCounts = @Counts

   
-- 取得分页总数
    set @pageCount = ( @tmpCounts + @pageSize - 1 ) / @pageSize

   
/**当前页大于总页数 取最后一页**/
   
if @page > @pageCount
       
set @page = @pageCount

   
-- /*-----数据分页2分处理-------*/
    declare @pageIndex int -- 总数/页大小
    declare @lastcount int -- 总数%页大小

   
set @pageIndex = @tmpCounts / @pageSize
   
set @lastcount = @tmpCounts % @pageSize
   
if @lastcount > 0
       
set @pageIndex = @pageIndex + 1
   
else
       
set @lastcount = @pagesize

   
-- //***显示分页
    if @strCondition is null or @strCondition = ''      -- 没有设置显示条件
    begin
       
if @pageIndex < 2 or @page <= @pageIndex / 2 + @pageIndex % 2    -- 前半部分数据处理
            begin
               
if @page = 1
                   
set @strTmp = @SqlSelect + ' top ' + CAST ( @pageSize as VARCHAR ( 4 )) + ' ' + @fldName + ' from ' + @tblName                        
                       
+ ' order by ' + @fldSort + ' ' + @strFSortType
               
else
               
begin                    
                   
set @strTmp = @SqlSelect + ' top ' + CAST ( @pageSize as VARCHAR ( 4 )) + ' ' + @fldName + ' from ' + @tblName
                       
+ ' where ' + @ID + ' <(select min( ' + @ID + ' ) from ( ' + @SqlSelect + ' top ' + CAST ( @pageSize * ( @page - 1 ) as Varchar ( 20 )) + ' ' + @ID + ' from ' + @tblName
                       
+ ' order by ' + @fldSort + ' ' + @strFSortType + ' ) AS TBMinID) '
                       
+ ' order by ' + @fldSort + ' ' + @strFSortType
               
end    
           
end
       
else
           
begin
           
set @page = @pageIndex - @page + 1 -- 后半部分数据处理
                if @page <= 1 -- 最后一页数据显示               
                    set @strTmp = @SqlSelect + ' * from ( ' + @SqlSelect + ' top ' + CAST ( @lastcount as VARCHAR ( 4 )) + ' ' + @fldName + ' from ' + @tblName
                       
+ ' order by ' + @fldSort + ' ' + @strSortType + ' ) AS TempTB ' + ' order by ' + @fldSort + ' ' + @strFSortType
               
else
                   
set @strTmp = @SqlSelect + ' * from ( ' + @SqlSelect + ' top ' + CAST ( @pageSize as VARCHAR ( 4 )) + ' ' + @fldName + ' from ' + @tblName
                       
+ ' where ' + @ID + ' >(select max( ' + @ID + ' ) from( ' + @SqlSelect + ' top ' + CAST ( @pageSize * ( @page - 2 ) + @lastcount as Varchar ( 20 )) + ' ' + @ID + ' from ' + @tblName
                       
+ ' order by ' + @fldSort + ' ' + @strSortType + ' ) AS TBMaxID) '
                       
+ ' order by ' + @fldSort + ' ' + @strSortType + ' ) AS TempTB ' + ' order by ' + @fldSort + ' ' + @strFSortType
           
end
   
end

   
else -- 有查询条件
    begin
       
if @pageIndex < 2 or @page <= @pageIndex / 2 + @pageIndex % 2    -- 前半部分数据处理
        begin
               
if @page = 1
                   
set @strTmp = @SqlSelect + ' top ' + CAST ( @pageSize as VARCHAR ( 4 )) + ' ' + @fldName + ' from ' + @tblName                        
                       
+ ' where 1=1 ' + @strCondition + ' order by ' + @fldSort + ' ' + @strFSortType
               
else
               
begin                    
                   
set @strTmp = @SqlSelect + ' top ' + CAST ( @pageSize as VARCHAR ( 4 )) + ' ' + @fldName + ' from ' + @tblName
                       
+ ' where ' + @ID + ' <(select min( ' + @ID + ' ) from ( ' + @SqlSelect + ' top ' + CAST ( @pageSize * ( @page - 1 ) as Varchar ( 20 )) + ' ' + @ID + ' from ' + @tblName
                       
+ ' where (1=1) ' + @strCondition + ' order by ' + @fldSort + ' ' + @strFSortType + ' ) AS TBMinID) '
                       
+ ' ' + @strCondition + ' order by ' + @fldSort + ' ' + @strFSortType
               
end            
       
end
       
else
       
begin
           
set @page = @pageIndex - @page + 1 -- 后半部分数据处理
            if @page <= 1 -- 最后一页数据显示
                    set @strTmp = @SqlSelect + ' * from ( ' + @SqlSelect + ' top ' + CAST ( @lastcount as VARCHAR ( 4 )) + ' ' + @fldName + ' from ' + @tblName
                       
+ ' where (1=1) ' + @strCondition + ' order by ' + @fldSort + ' ' + @strSortType + ' ) AS TempTB ' + ' order by ' + @fldSort + ' ' + @strFSortType                     
           
else
                   
set @strTmp = @SqlSelect + ' * from ( ' + @SqlSelect + ' top ' + CAST ( @pageSize as VARCHAR ( 4 )) + ' ' + @fldName + ' from ' + @tblName
                       
+ ' where ' + @ID + ' >(select max( ' + @ID + ' ) from( ' + @SqlSelect + ' top ' + CAST ( @pageSize * ( @page - 2 ) + @lastcount as Varchar ( 20 )) + ' ' + @ID + ' from ' + @tblName
                       
+ ' where (1=1) ' + @strCondition + ' order by ' + @fldSort + ' ' + @strSortType + ' ) AS TBMaxID) '
                       
+ ' ' + @strCondition + ' order by ' + @fldSort + ' ' + @strSortType + ' ) AS TempTB ' + ' order by ' + @fldSort + ' ' + @strFSortType                
       
end    
   
end

-- ----返回查询结果-----
exec sp_executesql @strTmp
-- print @strTmp
SET NOCOUNT OFF
GO

调用方法列子:
/// <summary>
   
/// 通用分页数据读取函数
   
/// 注意:在函数调用外部打开和关闭连接,以及关闭数据读取器
   
/// </summary>
   
/// <param name="comm">SqlCommand对象</param>
   
/// <param name="_tblName">查询的表/表联合</param>
   
/// <param name="_fldName">要查询的字段名</param>
   
/// <param name="_pageSize">每页数据大小</param>
   
/// <param name="_page">当前第几页</param>
   
/// <param name="_fldSort">排序字段</param>
   
/// <param name="_Sort">排序顺序0降序1升序</param>
   
/// <param name="_strCondition">过滤条件</param>
   
/// <param name="_ID">主表主键</param>       
   
/// <param name="_dr">返回的SqlDataReader ref</param>

    public static void CutPageData(SqlConnection conn, ref SqlCommand comm, string _tblName, string _fldName, int _pageSize, int _page, string _fldSort, int _Sort, string _strCondition, string _ID, ref SqlDataReader _dr)
   
{
       
//注意:在函数调用外部打开和关闭连接,以及关闭数据读取器
       
//comm = new SqlCommand("proc_ListPage",conn);
       
//comm.CommandType = CommandType.StoredProcedure;
        comm.Parameters.Add("@tblName", SqlDbType.NVarChar, 200);
        comm.Parameters[
"@tblName"].Value = _tblName;
        comm.Parameters.Add(
"@fldName", SqlDbType.NVarChar, 500);
        comm.Parameters[
"@fldName"].Value = _fldName;
        comm.Parameters.Add(
"@pageSize", SqlDbType.Int);
        comm.Parameters[
"@pageSize"].Value = _pageSize;
        comm.Parameters.Add(
"@page", SqlDbType.Int);
        comm.Parameters[
"@page"].Value = _page;
        comm.Parameters.Add(
"@fldSort", SqlDbType.NVarChar, 200);
        comm.Parameters[
"@fldSort"].Value = _fldSort;
        comm.Parameters.Add(
"@Sort", SqlDbType.Bit);
        comm.Parameters[
"@Sort"].Value = _Sort;
        comm.Parameters.Add(
"@strCondition", SqlDbType.NVarChar, 1000);
        comm.Parameters[
"@strCondition"].Value = _strCondition;
        comm.Parameters.Add(
"@ID", SqlDbType.NVarChar, 150);
        comm.Parameters[
"@ID"].Value = _ID;
        comm.Parameters.Add(
"@Counts", SqlDbType.Int, 0);
        comm.Parameters[
"@Counts"].Direction = ParameterDirection.Output;
        comm.Parameters.Add(
"@pageCount", SqlDbType.Int, 0);
        comm.Parameters[
"@pageCount"].Direction = ParameterDirection.Output;

        _dr
= comm.ExecuteReader();
    }

调用例如:
CutPageData(conn, ref comm, "VOX_CDSinger", "id, cdsinger, cdsingertype, area, cdsingerreadme", 15, page, "id", 1, strFilter, "id", ref dr);
对应说明:
CutPageData(数据连接对象, ref Sqlcommand对象, "需要表或视图名称", "要查询的字段", 每页读取数据条数, 当前页, " 排序字段可多字段如(addtime desc, visitcounts注意这里最后一个字段不加desc或asc 最后一个字段对应于后面的排序规则)", 排序方式(1 desc 0 asc), where条件(这里不再添加where条件添加如:' and visitcounts>100'), 表主键, ref 返回的SqlDataReader对象);



查看评论
9楼 mingch 2009-05-30 22:12发表[回复]
有问题呀
如果总页数有46页,到了第24页就出错了

多次为 'TempTB' 指定了列 'XXXXXXXX'
8楼 ss 2008-05-04 08:48发表[回复]
联合查询出错
7楼 分页有问题 2007-08-28 17:27发表[回复]
分页有问题
6楼 hertcloud 2007-06-15 09:35发表[回复]
多 条件不会出错啊.
调用的时候
请 使用
condition += " and name like'"+ key1 +"'";
condition += " and grade ="+ key21;
...这样的方式
5楼 kk 2007-06-08 14:18发表[回复]
原来那条件是要加上 and 的。
4楼 kk 2007-06-08 14:01发表[回复]
晕。添加条件会出错
3楼 lai_gb 2007-05-24 09:50发表[回复]
多条件情况下会出错啊~~有没有改善版呢?请发一份给我好么?谢谢!!
[email protected]
2楼 paleyyang 2007-04-12 09:17发表[回复]
这个存储过程加条件后就出错呀。
还有你另一个修改版的。只能显示第一页和最后一页的。
1楼 weiqiaoxyz 2007-04-11 22:11发表[回复] [引用] [举报]
能不能给个实例啊,从未接触过存储过程分页

望能提供~!

你可能感兴趣的:(not in)