• SQL Server 存储过程的分页




    /****** Object: Stored Procedure dbo.GetRecordFromPage Script Date: 2006-2-24 23:06:43 ******/

    /*
    经测试,在 14483461 条记录中查询第 100000 页,每页 10 条记录按升序和降序第一次时间均为 0.47 秒,第二次时间均为 0.43 秒,测试语法如下:
    exec GetRecordFromPage news,newsid,10,100000
    exec GetRecordFromPage QW_LW,ID,'*',10,2,0,'MC LIKE ''%%'''
    news 为 表名, newsid 为关键字段, 使用时请先对 newsid 建立索引。
    */

    /*
    函数名称: GetRecordFromPage
    函数功能: 获取指定页的数据
    参数说明: @tblName 包含数据的表名
    @fldName 关键字段名
    @strGotFields 需要返回的列,返回全部用*
    @PageSize 每页记录数
    @PageIndex 要获取的页码
    @OrderType 排序类型, 0 - 升序, 1 - 降序
    @strWhere 查询条件 (注意: 不要加 where)

    作 者: 铁拳
    邮 箱: sunjianhua_kki@sina.com
    创建时间: 2004-07-04
    修改时间: 2004-07-04
    */
    CREATE PROCEDURE GetRecordFromPage
    @tblName varchar(255), -- 表名
    @fldName varchar(255), -- 关键字段名
    @strGotFields varchar(1000) = '*',-- 需要返回的列
    @PageSize int = 10, -- 页尺寸
    @PageIndex int = 1, -- 页码
    @OrderType bit = 0, -- 设置排序类型, 非 0 值则降序
    @strWhere varchar(2000) = '' -- 查询条件 (注意: 不要加 where)
    AS

    declare @strSQL varchar(6000) -- 主语句
    declare @strTmp varchar(1000) -- 临时变量
    declare @strOrder varchar(500) -- 排序类型

    if @OrderType != 1
    begin
    set @strTmp = '<(select min'
    set @strOrder = ' order by [' + @fldName + '] desc'
    end
    else
    begin
    set @strTmp = '>(select max'
    set @strOrder = ' order by [' + @fldName +'] asc'
    end

    set @strSQL = 'select top ' + str(@PageSize) + @strGotFields + ' from ['
    + @tblName + '] where [' + @fldName + ']' + @strTmp + '(['
    + @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['
    + @fldName + '] from [' + @tblName + ']' + @strOrder + ') as tblTmp)'
    + @strOrder

    if @strWhere != ''
    set @strSQL = 'select top ' + str(@PageSize) + @strGotFields + ' from ['
    + @tblName + '] where [' + @fldName + ']' + @strTmp + '(['
    + @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['
    + @fldName + '] from [' + @tblName + '] where ' + @strWhere
    + @strOrder + ') as tblTmp) and ' + @strWhere + @strOrder

    if @PageIndex = 1
    begin
    set @strTmp = ''
    if @strWhere != ''
    set @strTmp = ' where (' + @strWhere + ')'

    set @strSQL = 'select top ' + str(@PageSize) + @strGotFields + ' from ['
    + @tblName + ']' + @strTmp + ' ' + @strOrder
    end

    exec (@strSQL)


    GO












    ========================================================================


    建立表:

    CREATE TABLE [TestTable] (
    [ID] [int] IDENTITY (1, 1) NOT NULL ,
    [FirstName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,
    [LastName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,
    [Country] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
    [Note] [nvarchar] (2000) COLLATE Chinese_PRC_CI_AS NULL
    ) ON [PRIMARY]
    GO

     

    插入数据:(2万条,用更多的数据测试会明显一些)
    SET IDENTITY_INSERT TestTable ON

    declare @i int
    set @i=1
    while @i<=20000
    begin
    insert into TestTable([id], FirstName, LastName, Country,Note) values(@i, ''FirstName_XXX'',''LastName_XXX'',''Country_XXX'',''Note_XXX'')
    set @i=@i+1
    end

    SET IDENTITY_INSERT TestTable OFF

     

    -------------------------------------

    分页方案一:(利用Not In和SELECT TOP分页)
    语句形式:
    SELECT TOP 10 *
    FROM TestTable
    WHERE (ID NOT IN
    (SELECT TOP 20 id
    FROM TestTable
    ORDER BY id))
    ORDER BY ID


    SELECT TOP 页大小 *
    FROM TestTable
    WHERE (ID NOT IN
    (SELECT TOP 页大小*页数 id
    FROM 表
    ORDER BY id))
    ORDER BY ID

    -------------------------------------

    分页方案二:(利用ID大于多少和SELECT TOP分页)
    语句形式:
    SELECT TOP 10 *
    FROM TestTable
    WHERE (ID >
    (SELECT MAX(id)
    FROM (SELECT TOP 20 id
    FROM TestTable
    ORDER BY id) AS T))
    ORDER BY ID


    SELECT TOP 页大小 *
    FROM TestTable
    WHERE (ID >
    (SELECT MAX(id)
    FROM (SELECT TOP 页大小*页数 id
    FROM 表
    ORDER BY id) AS T))
    ORDER BY ID


    -------------------------------------

    分页方案三:(利用SQL的游标存储过程分页)
    create procedure XiaoZhengGe
    @sqlstr nvarchar(4000), --查询字符串
    @currentpage int, --第N页
    @pagesize int --每页行数
    as
    set nocount on
    declare @P1 int, --P1是游标的id
    @rowcount int
    exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output
    select ceiling(1.0*@rowcount/@pagesize) as 总页数--,@rowcount as 总行数,@currentpage as 当前页
    set @currentpage=(@currentpage-1)*@pagesize+1
    exec sp_cursorfetch @P1,16,@currentpage,@pagesize
    exec sp_cursorclose @P1
    set nocount off

    其它的方案:如果没有主键,可以用临时表,也可以用方案三做,但是效率会低。
    建议优化的时候,加上主键和索引,查询效率会提高。

    通过SQL 查询分析器,显示比较:我的结论是:
    分页方案二:(利用ID大于多少和SELECT TOP分页)效率最高,需要拼接SQL语句
    分页方案一:(利用Not In和SELECT TOP分页) 效率次之,需要拼接SQL语句
    分页方案三:(利用SQL的游标存储过程分页) 效率最差,但是最为通用

    在实际情况中,要具体分析。

  • 相关阅读:
    PHP-xml-1
    BZOJ 1833 ZJOI2010 count 数字计数 数位DP
    运算符总结
    大写和小写转换
    Java基础:泛型
    Codeforces Round #156 (Div. 2)---A. Greg&#39;s Workout
    【Git】GitHub for Windows使用(2) 分支
    【Git】GitHub for Windows使用(1)
    【java JVM】JVM中类的加载,加载class文件的原理机制
    【FTP】org.apache.commons.net.ftp.FTPClient实现复杂的上传下载,操作目录,处理编码
  • 原文地址:https://www.cnblogs.com/winner/p/338649.html
Copyright © 2020-2023  润新知