• 步步为营:SQL通用存储过程分页


    这个通用分页维护了好久,也经过需求变化不断的修改.小弟不才,写得不够好..请大虾莫喷..

    放出来纯属交流学习,当然分页方式还有好多好多,我们可以讨论性能和优化,帮助自己不断的提高。

    第一种使用NOTIN的方式进行分页。

    USE [Data]
    GO
    /****** Object: StoredProcedure [dbo].[P_CommonPager_NotIn] Script Date: 11/22/2011 16:24:11 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    -- =============================================
    --
    Author: 薛凯
    --
    Create date: 2011年11月22日
    --
    Description: 通用存储过程分页 NOT IN 方式
    --
    =============================================
    IF EXISTS (SELECT 1 FROM SYSOBJECTS WHERE id = object_id('P_CommonPager_RowNomber') AND TYPE = 'P')
    DROP PROC P_MoveShikeeChange
    GO
    CREATE PROCEDURE [dbo].[P_CommonPager_NotIn] --P_CommonPager_NotIn 'View_TrySpr','View_TrySpr.*','tid','order by num desc','and trybrand=1',2,10,4444,1
    @tblName VARCHAR(255)='sk_Users', -- 表名如:'xtest'
    @strGetFields VARCHAR(1000) = '*', -- 需要返回的列如:'xname,xdemo'
    @pkName NVARCHAR(50)='uid', -- 主键名
    @strOrder VARCHAR(255)='order by uid desc', -- 排序的字段名如:'order by id desc'
    @strWhere VARCHAR(max) = '1=1', -- 查询条件(注意:不要加where)如:'xname like ''%222name%'''
    @pageIndex INT = 1, -- 页码如:2
    @pageSize INT = 20, -- 每页记录数如:20
    @recordCount INT=0 OUTPUT, -- 记录总数
    @doCount INT=0 -- 非0则统计,为0则不统计(统计会影响效率)
    AS
    DECLARE @sql NVARCHAR(MAX)
    DECLARE @sqltemp NVARCHAR(MAX)
    DECLARE @strCount NVARCHAR(MAX)
    DECLARE @pageCount NVARCHAR(MAX)
    SET @sql=' From '+@tblName
    BEGIN

    IF(@strWhere!='')
    SET @sql=@sql+' Where '+@strWhere
    --总记录条数
    IF(@doCount!=0)
    BEGIN
    IF(@strWhere !='')
    BEGIN
    SET @strCount='set @recordCount=(select count(1) from '+ @tblName + ' where '+@strWhere+' )'
    END
    ELSE
    BEGIN
    SET @strCount='set @recordCount=(select count(1) from '+ @tblName + ' )'
    END
    print @strCount
    EXECUTE sp_executesql @strCount ,N'@recordCount INT output',@recordCount OUTPUT
    END

    --计算出总页数
    SET @pageCount = @recordCount / @pageSize
    IF(@recordCount % @pageSize != 0)
    BEGIN
    SET @pageCount = @pageCount + 1
    END
    --如果查询页数大于总页数
    IF(@PageIndex > @pageCount)
    BEGIN
    SET @PageIndex = @pageCount
    END

    IF @strWhere !=''
    BEGIN
    SET @strWhere=' where '+@strWhere
    END

    IF (@PageIndex>1)
    BEGIN
    SET @sqltemp=@PKName+' not in (Select Top '+CAST((@PageSize*(@PageIndex-1)) AS NVARCHAR)+''+@PKName+''+@sql
    IF(@strOrder!='')SET @sqltemp=@sqltemp+''+@strOrder
    SET @sqltemp=@sqltemp+')'
    SET @sql='Select Top '+CAST(@PageSize AS NVARCHAR)+''+@strGetFields+''+@sql
    IF(@strWhere!='')
    SET @sql=@sql+' And '+@sqltemp
    ELSE
    SET @sql=@sql+' Where '+@sqltemp
    END
    ELSE
    BEGIN
    SET @sql='Select Top '+CAST(@PageSize AS NVARCHAR)+''+@strGetFields+''+@sql
    END
    IF(@strOrder!='')
    SET @sql=@sql+''+@strOrder
    PRINT @sql
    EXEC(@sql)
    END

    第二种方式是使用RowNomber进行分页。我比较喜欢使用这种,速度比NOTIN要快(推荐)

    USE [Data]
    GO
    /****** Object: StoredProcedure [dbo].[P_CommonPager_RowNomber] Script Date: 11/22/2011 16:26:20 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    -- =============================================
    --
    Author: 薛凯
    --
    Create date: 2011年11月22日
    --
    Description: 通用存储过程分页 ROW_NUMBER 方式
    --
    =============================================
    IF EXISTS (SELECT 1 FROM SYSOBJECTS WHERE id = object_id('P_CommonPager_RowNomber') AND TYPE = 'P')
    DROP PROC P_MoveShikeeChange
    GO
    CREATE PROCEDURE [dbo].[P_CommonPager_RowNomber]
    @tblName VARCHAR(255)='sk_Users', -- 表名如:'xtest'
    @strGetFields VARCHAR(1000) = '*', -- 需要返回的列如:'xname,xdemo'
    @strOrder VARCHAR(255)='order by uid desc', -- 排序的字段名如:'order by id desc'
    @strWhere VARCHAR(max) = '1=1', -- 查询条件(注意:不要加where)如:'xname like ''%222name%'''
    @pageIndex INT = 1, -- 页码如:2
    @pageSize INT = 20, -- 每页记录数如:20
    @recordCount INT=0 output, -- 记录总数
    @doCount INT=0 -- 非0则统计,为0则不统计(统计会影响效率)
    AS
    DECLARE @strSQL NVARCHAR(MAX)
    DECLARE @strCount NVARCHAR(MAX)
    DECLARE @pageCount NVARCHAR(MAX)
    BEGIN
    --总记录条数
    IF(@doCount!=0)
    BEGIN
    IF(@strWhere !='')
    BEGIN
    SET @strCount='set @num=(select count(1) from '+ @tblName + ' where '+@strWhere+' )'
    END
    ELSE
    BEGIN
    SET @strCount='set @num=(select count(1) from '+ @tblName + ' )'
    END
    EXECUTE sp_executesql @strCount ,N'@num INT output',@recordCount OUTPUT
    END

    --计算出总页数
    SET @pageCount = @recordCount / @pageSize
    IF(@recordCount % @pageSize != 0)
    BEGIN
    SET @pageCount = @pageCount + 1
    END
    --如果查询页数大于总页数
    IF(@PageIndex > @pageCount)
    BEGIN
    SET @PageIndex = @pageCount
    END

    IF @strWhere !=''
    BEGIN
    SET @strWhere = ' where ' + @strWhere
    END
    SET @strSQL = 'SELECT * FROM (SELECT ROW_NUMBER() OVER ('+@strOrder+') AS ROWID,'

    SET @strSQL = @strSQL + @strGetFields + ' FROM '+@tblName+''+ @strWhere

    SET @strSQL = @strSQL+') AS sp WHERE ROWID BETWEEN ' + STR((@PageIndex-1) * @PageSize + 1)

    SET @strSQL = @strSQL + ' AND ' + STR(@PageIndex*@PageSize)
    PRINT @strSQL
    EXEC (@strSQL)
    END

    下面再写出配合昨天我修改的分页查询按每段100页的分页导航算法

           #region 淘宝论坛分页方式
    ///<summary>
    /// 淘宝论坛分页方式
    ///</summary>
    ///<param name="sumCount">总条数</param>
    ///<param name="pageSize">每页大小</param>
    ///<param name="thisIndex">当前页</param>
    ///<param name="webstr">分页字符串page=[$ToPage$]</param>
    ///<returns></returns>
    public static string BindPageText10(int sumCount, int pageSize, int thisIndex, string webstr)
    {
    StringBuilder strHtml = new StringBuilder();
    int endPage = 0;
    int sumPage = 0;
    //计算总页数,获得总页数
    int pageCount = sumCount / pageSize;
    //如果不能正常取余就给总页数 加1
    if (sumCount % pageSize != 0)
    pageCount += 1;//获得
    //如果输入的页数大于总页数那么页数就是总页数
    if (thisIndex > pageCount)
    thisIndex = pageCount;
    //按100分段总页数,
    sumPage = pageCount / 100;
    for (int i = 1; i <= sumPage; i++)
    {
    if (thisIndex < i * 100)
    {
    pageCount = i * 100;
    break;
    }
    }
    //如果当前页 等于零 就设定当前页是 第一页
    if (thisIndex == 0)
    {
    thisIndex = 1;
    }
    //如果当前页大于第1页的都显示 [上一页]按钮 给用户点击
    //实现 [上一页]
    if (thisIndex > 1)
    {
    strHtml.Append("<a href=\"");
    strHtml.Append(webstr.Replace("[$ToPage$]", Convert.ToString(thisIndex - 1)));
    strHtml.Append("\" title=\"上一页\" class=\"prev\"><b class=\"trigon\"></b><span>上一页</span></a>");
    }
    //如果当前页大于第1页 总页数也大于1页
    //实现 [上一页] [1]
    if (thisIndex > 1 && pageCount > 1)
    {
    strHtml.Append("<a href=\"");
    strHtml.Append(webstr.Replace("[$ToPage$]", "1"));
    strHtml.Append("\" title=\"当前: 1\">1</a>");
    }
    //如果当前页大于第2页 总页数也大于2页
    //实现 [上一页] [1][2]
    if (thisIndex > 2 && pageCount > 2)
    {
    strHtml.Append("<a href=\"");
    strHtml.Append(webstr.Replace("[$ToPage$]", "2"));
    strHtml.Append("\" title=\"当前: 2\">2</a>");
    }
    //如果当前页大于等于第6页
    if (thisIndex >= 6)
    {
    strHtml.Append("<span class=\"etc\">...</span>");
    }
    //如果总页数 大于 当前页+两页之后的页数
    //否则末尾页就是总页数
    if (pageCount > thisIndex + 2)
    endPage = thisIndex + 2;
    else
    endPage = pageCount;
    //循环遍历 假如当前页为 第6页
    //实现 [上一页] [1][2]...[4][5] 6 [7][8]
    //中间页数 [4][5] 6 [7][8]
    for (int i = thisIndex - 2; i <= endPage; i++)
    {
    if (i > 0)
    {
    if (i == thisIndex)
    strHtml.Append("<a href=\"javascript:;\" class=\"sel\">" + i + "</a>");//当前选中页
    else
    {
    if (i != 1 && i != pageCount && i != 2 && i != pageCount - 1)
    {
    strHtml.Append("<a href=\"");
    strHtml.Append(webstr.Replace("[$ToPage$]", Convert.ToString(i)));
    strHtml.Append("\" title=\"当前: ");
    strHtml.Append(i);
    strHtml.Append("\">");
    strHtml.Append(i);
    strHtml.Append("</a>");
    }
    else
    {
    //解决是第一页的时候不显示第二页的导航
    //解决是最后页的时候不显示倒数第二页的导航
    if (thisIndex == 1 || thisIndex == pageCount)
    {
    strHtml.Append("<a href=\"");
    strHtml.Append(webstr.Replace("[$ToPage$]", Convert.ToString(i)));
    strHtml.Append("\" title=\"当前: ");
    strHtml.Append(i);
    strHtml.Append("\">");
    strHtml.Append(i);
    strHtml.Append("</a>");
    }
    }
    }
    }
    }
    //如果当前页 +3页之后的页数小于总页数
    //实现 [上一页] [1][2]...[4][5] 6 [7][8]...
    if (thisIndex + 3 < pageCount)
    strHtml.Append("<span class=\"etc\">...</span>");
    //如果当前页 不是最后一页 - 1 之后的页数
    //实现 [上一页] [1][2]...[4][5] 6 [7][8]...[99]
    if (thisIndex != pageCount - 1 && pageCount - 1 != 0 && thisIndex < pageCount)
    {
    strHtml.Append("<a href=\"");
    strHtml.Append(webstr.Replace("[$ToPage$]", Convert.ToString(pageCount - 1)));
    strHtml.Append("\" title=\"当前: ");
    strHtml.Append(pageCount - 1);
    strHtml.Append("\">");
    strHtml.Append(pageCount - 1);
    strHtml.Append("</a>");
    }
    //如果当前页 不是最后一页
    //实现 [上一页] [1][2]...[4][5] 6 [7][8]...[99][100]
    if (thisIndex != pageCount && pageCount != 0)
    {
    strHtml.Append("<a href=\"");
    strHtml.Append(webstr.Replace("[$ToPage$]", Convert.ToString(pageCount)));
    strHtml.Append("\" title=\"当前: ");
    strHtml.Append(pageCount);
    strHtml.Append("\">");
    strHtml.Append(pageCount);
    strHtml.Append("</a>");
    }
    if (thisIndex + 1 <= pageCount)
    {
    strHtml.Append("<a href=\"");
    strHtml.Append(webstr.Replace("[$ToPage$]", Convert.ToString(thisIndex + 1)));
    strHtml.Append("\" title=\"下一页\" class=\"next\"><span>下一页</span><b class=\"trigon\"></b></a>");
    }
    //strHtml.Append("<span class=\"go-page\"><em>共" + pageCount + "页</em>");
    strHtml.Append("</span>");
    string str = strHtml.ToString();
    return strHtml.ToString();
    }
    #endregion


    模仿导航http://bbs.taobao.com/catalog/459501.htm?spm=1.46102.147302.28&

  • 相关阅读:
    94、二叉树的中序遍历 | JS
    102、二叉树的层序遍历 | JS
    111、二叉树的最小深度 | JS
    二叉树的先中后序遍历-JS非递归实现
    二叉树的先中后序遍历-JS递归实现
    深度和广度优先遍历-JS实现
    76、最小覆盖子串 | JS-字典
    extra1 二分查找与二叉判定树
    02 线性表的顺序存储
    原型、原型链、作用域、作用域链、闭包
  • 原文地址:https://www.cnblogs.com/79039535/p/2259028.html
Copyright © 2020-2023  润新知