zoukankan      html  css  js  c++  java
  • ORACLE SQLSERVER2005分页

    SQL SERVER 2005 分页


    select * from    
    (
            select row_number() over(order by FieldA) as RowNum, *
     from  TableA   
    ) t
     where   t.RowNum between 10 and 20


    SELECT TOP 20 * FROM (SELECT
       ROW_NUMBER() OVER (ORDER BY Namec) AS RowNumber,
       *
    FROM
       dbo.mem_member) _myResults
    WHERE
       RowNumber > 10000

    SELECT * FROM (SELECT
       ROW_NUMBER() OVER (ORDER BY Namec) AS RowNumber,
       *
    FROM
       dbo.mem_member) _myResults
    WHERE
       RowNumber between 10000 and 10020
     

    WITH OrderedResults AS

    (SELECT *, ROW_NUMBER() OVER (order by Namec) as RowNumber FROM dbo.mem_member)

    SELECT *

    FROM OrderedResults

    WHERE RowNumber between 10000 and 10020

    临时表方法

     1BEGIN
     2                DECLARE @PageLowerBound int
     3                DECLARE @PageUpperBound int
     4                
     5                -- Set the page bounds
     6                SET @PageLowerBound = 10000
     7                SET @PageUpperBound = 10020
     8
     9                -- Create a temp table to store the select results
    10                Create Table #PageIndex
    11                (
    12                    [IndexId] int IDENTITY (11NOT NULL,
    13                    [Id] varchar(18
    14                )
    15                
    16                -- Insert into the temp table
    17                declare @SQL as nvarchar(4000)
    18                SET @SQL = 'INSERT INTO #PageIndex (Id)'
    19                SET @SQL = @SQL + ' SELECT'
    20                SET @SQL = @SQL + ' TOP ' + convert(nvarchar@PageUpperBound)
    21                SET @SQL = @SQL + ' m_id'
    22                SET @SQL = @SQL + ' FROM dbo.mem_member'
    23                SET @SQL = @SQL + ' ORDER BY NameC'
    24                
    25                -- Populate the temp table
    26                exec sp_executesql @SQL
    27
    28                -- Return paged results
    29                SELECT O.*
    30                FROM
    31                    dbo.mem_member O,
    32                    #PageIndex PageIndex
    33                WHERE
    34                    PageIndex.IndexID > @PageLowerBound
    35                    AND O.[m_Id] = PageIndex.[Id]
    36                ORDER BY
    37                    PageIndex.IndexID
    38                
    39drop table #PageIndex            
    40                END

    表变量方法和临时表差不多, 就是用的内存太多.

    ROWCOUNT

     1begin
     2DECLARE @first_id varchar(18), @startRow int
     3    
     4SET ROWCOUNT 10000
     5SELECT @first_id = m_id FROM mem_member ORDER BY m_id
     6
     7SET ROWCOUNT 20
     8
     9SELECT m.* 
    10FROM mem_member m
    11WHERE m_id >= @first_id
    12ORDER BY m.m_id
    13
    14SET ROWCOUNT 0
    15end

    SQL Server存储过程设计和优化措施

     一、适合读者对象:数据库开发程序员,数据库的数据量很多,涉及到对SP(存储过程)的优化的项目开发人员,对数据库有浓厚兴趣的人。  

      二、介绍:在数据库的开发过程中,经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用SP来封装数据库操作。如果项目的SP较多,书写又没有一定的规范,将会影响以后的系统维护困难和大SP逻辑的难以理解,另外如果数据库的数据量大或者项目对SP的性能要求很,就会遇到优化的问题,否则速度有可能很慢,经过亲身经验,一个经过优化过的SP要比一个性能差的SP的效率甚至高几百倍。  

      三、内容:  

      1、开发人员如果用到其他库的Table或View,务必在当前库中建立View来实现跨库操作,最好不要直接使用“databse.dbo.table_name”,因为sp_depends不能显示出该SP所使用的跨库table或view,不方便校验。  

      2、开发人员在提交SP前,必须已经使用set showplan on分析过查询计划,做过自身的查询优化检查。  

      3、高程序运行效率,优化应用程序,在SP编写过程中应该注意以下几点:   

      a)SQL的使用规范:

       i. 尽量避免大事务操作,慎用holdlock子句,提高系统并发能力。

       ii. 尽量避免反复访问同一张或几张表,尤其是数据量较大的表,可以考虑先根据条件提取数据到临时表中,然后再做连接。

       iii. 尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该改写;如果使用了游标,就要尽量避免在游标循环中再进行表连接的操作。

       iv. 注意where字句写法,必须考虑语句顺序,应该根据索引顺序、范围大小来确定条件子句的前后顺序,尽可能的让字段顺序与索引顺序相一致,范围从大到小。

       v. 不要在where子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

       vi. 尽量使用exists代替select count(1)来判断是否存在记录,count函数只有在统计表中所有行数时使用,而且count(1)比count(*)更有效率。

       vii. 尽量使用“>=”,不要使用“>”。

       viii. 注意一些or子句和union子句之间的替换

       ix. 注意表之间连接的数据类型,避免不同类型数据之间的连接。

       x. 注意存储过程中参数和数据类型的关系。

       xi. 注意insert、update操作的数据量,防止与其他应用冲突。如果数据量超过200个数据页面(400k),那么系统将会进行锁升级,页级锁会升级成表级锁。   

      b)索引的使用规范:

       i. 索引的创建要与应用结合考虑,建议大的OLTP表不要超过6个索引。

       ii. 尽可能的使用索引字段作为查询条件,尤其是聚簇索引,必要时可以通过index index_name来强制指定索引

       iii. 避免对大表查询时进行table scan,必要时考虑新建索引。

       iv. 在使用索引字段作为条件时,如果该索引是联合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用。

       v. 要注意索引的维护,周期性重建索引,重新编译存储过程。  

      c)tempdb的使用规范:

       i. 尽量避免使用distinct、order by、group by、having、join、cumpute,因为这些语句会加重tempdb的负担。

       ii. 避免频繁创建和删除临时表,减少系统表资源的消耗。

       iii. 在新建临时表时,如果一次性插入数据量很大,那么可以使用select into代替create table,避免log,提高速度;如果数据量不大,为了缓和系统表的资源,建议先create table,然后insert。

       iv. 如果临时表的数据量较大,需要建立索引,那么应该将创建临时表和建立索引的过程放在单独一个子存储过程中,这样才能保证系统能够很好的使用到该临时表的索引。

        v. 如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncate table,然后drop table,这样可以避免系统表的较长时间锁定。

        vi. 慎用大的临时表与其他大表的连接查询和修改,减低系统表负担,因为这种操作会在一条语句中多次使用tempdb的系统表。  
      d)合理的算法使用:   

      根据上面已提到的SQL优化技术和ASE Tuning手册中的SQL优化内容,结合实际应用,采用多种算法进行比较,以获得消耗资源最少、效率最高的方法。具体可用ASE调优命令:set statistics io on, set statistics time on , set showplan on 等。

     一、前言:在经过一段时间的存储过程开发之后,写下了一些开发时候的小结和经验与大家共享,希望对大家有益,主要是针对Sybase和SQL Server数据库,但其它数据库应该有一些共性。



    二、适合读者对象:数据库开发程序员,数据库的数据量很多,涉及到对SP(存储过程)的优化的项目开发人员,对数据库有浓厚兴趣的人。

    三、介绍:在数据库的开发过程中,经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用SP来封装数据库操作。如果项目的SP较多,书写又没有一定的规范,将会影响以后的系统维护困难和大SP逻辑的难以理解,另外如果数据库的数据量大或者项目对SP的性能要求很,就会遇到优化的问题,否则速度有可能很慢,经过亲身经验,一个经过优化过的SP要比一个性能差的SP的效率甚至高几百倍。

    四、    内容:

    1、开发人员如果用到其他库的Table或View,务必在当前库中建立View来实现跨库操作,最好不要直接使用“databse.dbo.table_name”,因为sp_depends不能显示出该SP所使用的跨库table或view,不方便校验。



    2、开发人员在提交SP前,必须已经使用set showplan on分析过查询计划,做过自身的查询优化检查。



    3、高程序运行效率,优化应用程序,在SP编写过程中应该注意以下几点:

    a)    SQL的使用规范:

                 i.       尽量避免大事务操作,慎用holdlock子句,提高系统并发能力。

                ii.       尽量避免反复访问同一张或几张表,尤其是数据量较大的表,可以考虑先根据条件提取数据到临时表中,然后再做连接。

               iii.       尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该改写;如果使用了游标,就要尽量避免在游标循环中再进行表连接的操作。

               iv.       注意where字句写法,必须考虑语句顺序,应该根据索引顺序、范围大小来确定条件子句的前后顺序,尽可能的让字段顺序与索引顺序相一致,范围从大到小。

                v.       不要在where子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

               vi.       尽量使用exists代替select count(1)来判断是否存在记录,count函数只有在统计表中所有行数时使用,而且count(1)比count(*)更有效率。

              vii.       尽量使用“>=”,不要使用“>”。

             viii.       注意一些or子句和union子句之间的替换

               ix.       注意表之间连接的数据类型,避免不同类型数据之间的连接。

                x.       注意存储过程中参数和数据类型的关系。

               xi.       注意insert、update操作的数据量,防止与其他应用冲突。如果数据量超过200个数据页面(400k),那么系统将会进行锁升级,页级锁会升级成表级锁。



    b)    索引的使用规范:

                 i.       索引的创建要与应用结合考虑,建议大的OLTP表不要超过6个索引。

                ii.       尽可能的使用索引字段作为查询条件,尤其是聚簇索引,必要时可以通过index index_name来强制指定索引

               iii.       避免对大表查询时进行table scan,必要时考虑新建索引。

               iv.       在使用索引字段作为条件时,如果该索引是联合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用。

                v.       要注意索引的维护,周期性重建索引,重新编译存储过程。



    c)    tempdb的使用规范:

                 i.       尽量避免使用distinct、order by、group by、having、join、cumpute,因为这些语句会加重tempdb的负担。

                ii.       避免频繁创建和删除临时表,减少系统表资源的消耗。

               iii.       在新建临时表时,如果一次性插入数据量很大,那么可以使用select into代替create table,避免log,提高速度;如果数据量不大,为了缓和系统表的资源,建议先create table,然后insert。

               iv.       如果临时表的数据量较大,需要建立索引,那么应该将创建临时表和建立索引的过程放在单独一个子存储过程中,这样才能保证系统能够很好的使用到该临时表的索引。

                v.       如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncate table,然后drop table,这样可以避免系统表的较长时间锁定。

               vi.       慎用大的临时表与其他大表的连接查询和修改,减低系统表负担,因为这种操作会在一条语句中多次使用tempdb的系统表。



    d)    合理的算法使用:

    根据上面已提到的SQL优化技术和ASE Tuning手册中的SQL优化内容,结合实际应用,采用多种算法进行比较,以获得消耗资源最少、效率最高的方法。具体可用ASE调优命令:set statistics io on, set statistics time on , set showplan on 等。

    ORACLE分页

    1. 最好还是利用分析函数
    row_number() over ( partition by col1 order by col2 )

    比如想取出100-150条记录,按照tname排序

    select tname,taBType from (
       select tname,tabtype,row_number() over ( order by tname ) rn from tab
    )
    where rn between 100 and 150;

    2. 直接使用rownum 虚列
    select tname,tabtype from (
       select tname,tabtype,rownum rn from tab where rownum <= 150
    )
    where rn >= 100;
    使用序列不能基于整个记录集合进行排序,假如指定了order by子句,排序的的是选出来的记录集的排序.

    ------------------------------------------------------------------------
    经过我的测试,在100万条数据的表中,检索数据的时候,方法2的速度要比方法1要快的.

    http://www.4guysfromrolla.com/webtech/042606-1.shtml

    http://www.4guysfromrolla.com/webtech/041206-1.shtml

    http://www.singingeels.com/Articles/Pagination_In_SQL_Server_2005.aspx

    http://blog.itpub.net/category/2879/5348

    建立聚集索引要求的:“既不能绝大多数都相同,又不能只有极少数相同”的规则

    何时使用聚集索引或非聚集索引

    下面的表总结了何时使用聚集索引或非聚集索引(很重要)。

    动作描述

    使用聚集索引

    使用非聚集索引

    列经常被分组排序

    返回某范围内的数据

    不应

    一个或极少不同值

    不应

    不应

    小数目的不同值

    不应

    大数目的不同值

    不应

    频繁更新的列

    不应

    外键列

    主键列

    频繁修改索引列

    不应


     http://richardhan.bokee.com/1332240.html

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

    /*
      函数名称: GetRecordFromPage
      函数功能: 获取指定页的数据
      参数说明: @tblName      包含数据的表名
               @fldName      关键字段名
               @PageSize     每页记录数
               @PageIndex    要获取的页码
               @OrderType    排序类型, 0 - 升序, 1 - 降序
               @strWhere     查询条件 (注意: 不要加 where)
      作  者: 铁拳
      邮  箱:
    unjianhua_kki@sina.com">sunjianhua_kki@sina.com
      创建时间: 2004-07-04
      修改时间: 2004-07-04
    */
    CREATE PROCEDURE GetRecordFromPage
        @tblName      varchar(255),       
    -- 表名
        @fldName      varchar(255),       -- 字段名
        @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 != 0
    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) + " * 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) + " * 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) + " * from ["
            + @tblName + "]" + @strTmp + " " + @strOrder
    end

    exec (@strSQL)

    GO


    改一下,看看这样是不是更好一点?
     

    /*

     函数名称: GetRecordFromPage

     函数功能: 获取指定页的数据

     参数说明:   @tblName        包含数据的表名

                 @fldName        关键字段名

                  @PageSize      每页记录数

                 @PageIndex    要获取的页码

                  @IsCount         是否要取得记录数

                 @OrderType    排序类型, 0 - 升序, 1 - 降序

                 @strWhere      查询条件(注意: 不要加where)

    */

    CREATE  PROCEDURE pGO_GetRecordFromPage

        @tblName      varchar(255),       -- 表名

        @fldName      varchar(255),       -- 字段名

        @PageSize     int = 10,           -- 页尺寸

        @PageIndex    int = 1,            -- 页码

        @IsCount      bit = 0,            -- 返回记录总数, 非0 值则返回

        @OrderType    bit = 0,            -- 设置排序类型, 非0 值则降序

        @strWhere     varchar(1000) = ''  -- 查询条件(注意: 不要加where)

    AS

     

    declare @strSQL   varchar(6000)       -- 主语句

    declare @strTmp   varchar(500)        -- 临时变量

    declare @strOrder varchar(400)        -- 排序类型

     

    -- 如果是查询记录总数,直接使用Count(0)函数

    if @IsCount != 0

     begin

     if @strWhere != ''

       set @strSQL = 'select count(*) as Total from [' + @tblName + '] where ' + @strWhere

     else

       set @strSQL = 'select count(*) as Total from [' + @tblName + '] '

     end

    --如果是想查询记录,则

    else

     begin

     if @PageIndex = 1

       begin

            set @strTmp = ''

            if @strWhere != ''

                 set @strTmp = ' where ' + @strWhere

     

            set @strSQL = 'select top ' + str(@PageSize) + ' * from ['

                 + @tblName + ']' + @strTmp + ' ' + @strOrder

       end

     else

       begin

        --如果是降序查询……

        if @OrderType != 0

         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

     

        if @strWhere != ''

             set @strSQL = 'select top ' + str(@PageSize) + ' * from ['

                  + @tblName + '] where [' + @fldName + ']' + @strTmp + '(['

                  + @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['

                  + @fldName + '] from [' + @tblName + '] where ' + @strWhere + ' '

                  + @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder

        else

         set @strSQL = 'select top ' + str(@PageSize) + ' * from ['

              + @tblName + '] where [' + @fldName + ']' + @strTmp + '(['

              + @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['

              + @fldName + '] from [' + @tblName + ']' + @strOrder + ') as tblTmp)'

              + @strOrder 

     

     

       end

    end

     

    exec (@strSQL)

    GO

     

     http://blog.csdn.net/evafly920/archive/2006/03/03/614813.ASPx

    /*

    ***************************************************************

    ** 千万数量级分页存储过程**

    ***************************************************************

    参数说明:

    1.Tables :表名称,视图

    2.PrimaryKey :主关键字

    3.Sort :排序语句,不带Order By 比如:NewsID Desc,OrderRows Asc

    4.CurrentPage :当前页码

    5.PageSize :分页尺寸

    6.Filter :过滤语句,不带Where

    7.Group :Group语句,不带Group By

    效果演示:http://www.cn5135.com/_App/Enterprise/QueryResult.aspx

    ***************************************************************/

    CREATE PROCEDURE CN5135_SP_Pagination

    (

        @Tables varchar(1000),

        @PrimaryKey varchar(100),

        @Sort varchar(200) = NULL,

        @CurrentPage int = 1,

        @PageSize int = 10,

        @Fields varchar(1000) = '*',

        @Filter varchar(1000) = NULL,

        @Group varchar(1000) = NULL

    )

    AS

    /*默认排序*/

    IF @Sort IS NULL OR @Sort = ''

         SET @Sort = @PrimaryKey

    DECLARE @SortTable varchar(100)

    DECLARE @SortName varchar(100)

    DECLARE @strSortColumn varchar(200)

    DECLARE @operator char(2)

    DECLARE @type varchar(100)

    DECLARE @prec int

    /*设定排序语句.*/

    IF CHARINDEX('DESC',@Sort)>0

    BEGIN

         SET @strSortColumn = REPLACE(@Sort, 'DESC', '')

         SET @operator = '<='

    END

    ELSE

    BEGIN

         IF CHARINDEX('ASC', @Sort) = 0

             SET @strSortColumn = REPLACE(@Sort, 'ASC', '')

         SET @operator = '>='

    END

    IF CHARINDEX('.', @strSortColumn) > 0

    BEGIN

         SET @SortTable = SUBSTRING(@strSortColumn, 0, CHARINDEX('.',@strSortColumn))

         SET @SortName = SUBSTRING(@strSortColumn, CHARINDEX('.',@strSortColumn) + 1, LEN(@strSortColumn))

    END

    ELSE

    BEGIN

         SET @SortTable = @Tables

         SET @SortName = @strSortColumn

    END

    SELECT @type=t.name, @prec=c.prec

    FROM sysobjects o

         JOIN syscolumns c on o.id=c.id

         JOIN systypes t on c.xusertype=t.xusertype

    WHERE o.name = @SortTable AND c.name = @SortName

    IF CHARINDEX('char', @type) > 0

         SET @type = @type + '(' + CAST(@prec AS varchar) + ')'

    DECLARE @strPageSize varchar(50)

    DECLARE @strStartRow varchar(50)

    DECLARE @strFilter varchar(1000)

    DECLARE @strSimpleFilter varchar(1000)

    DECLARE @strGroup varchar(1000)

    /*默认当前页*/

    IF @CurrentPage < 1

         SET @CurrentPage = 1

    /*设置分页参数.*/

    SET @strPageSize = CAST(@PageSize AS varchar(50))

    SET @strStartRow = CAST(((@CurrentPage - 1)*@PageSize + 1) AS varchar(50))

    /*筛选以及分组语句.*/

    IF @Filter IS NOT NULL AND @Filter != ''

    BEGIN

         SET @strFilter = ' WHERE ' + @Filter + ' '

         SET @strSimpleFilter = ' AND ' + @Filter + ' '

    END

    ELSE

    BEGIN

         SET @strSimpleFilter = ''

         SET @strFilter = ''

    END

    IF @Group IS NOT NULL AND @Group != ''

         SET @strGroup = ' GROUP BY ' + @Group + ' '

    ELSE

         SET @strGroup = ''

    /*执行查询语句*/

    EXEC(

    '

    DECLARE @SortColumn ' + @type + '

    SET ROWCOUNT ' + @strStartRow + '

    SELECT @SortColumn=' + @strSortColumn + ' FROM ' + @Tables + @strFilter + ' ' + @strGroup + ' ORDER BY ' + @Sort + '

    SET ROWCOUNT ' + @strPageSize + '

    SELECT ' + @Fields + ' FROM ' + @Tables + ' WHERE ' + @strSortColumn + @operator + ' @SortColumn ' + @strSimpleFilter + ' ' + @strGroup + ' ORDER BY ' + @Sort + '

    '

    )

    GO

    http://www.qqgb.com/DataDB/MSSQL/sqlMemory/DataDB_116339.html

    /*
    说明:1.支持多表查询 2.支持任意排序 3.不支持表别名
    参考了
        evafly920:[分享]千万数量级分页存储过程(效果演示)
        地址:http://blog.csdn.net/evafly920/archive/2006/03/03/614813.ASPx 

     

    IF(EXISTS(SELECT * FROM sysobjects WHERE [id]=OBJECT_ID('usp_PagingLarge') AND xtype='P'))

        DROP PROCEDURE usp_PagingLarge

    */

     

    GO

     

    CREATE PROCEDURE usp_PagingLarge

    @TableNames VARCHAR(200),    --表名,可以是多个表,但不能用别名

    @PrimaryKey VARCHAR(100),    --主键,可以为空,但@Order为空时该值不能为空

    @Fields    VARCHAR(200),        --要取出的字段,可以是多个表的字段,可以为空,为空表示select *

    @PageSize INT,            --每页记录数

    @CurrentPage INT,        --当前页,表示第页

    @Filter VARCHAR(200) = '',    --条件,可以为空,不用填where

    @Group VARCHAR(200) = '',    --分组依据,可以为空,不用填group by

    @Order VARCHAR(200) = ''    --排序,可以为空,为空默认按主键升序排列,不用填order by

    AS

    BEGIN

        DECLARE @SortColumn VARCHAR(200)

        DECLARE @Operator CHAR(2)

        DECLARE @SortTable VARCHAR(200)

        DECLARE @SortName VARCHAR(200)

        IF @Fields = ''

            SET @Fields = '*'

        IF @Filter = ''

            SET @Filter = 'WHERE 1=1'

        ELSE

            SET @Filter = 'WHERE ' + @Filter

        IF @Group <>''

            SET @Group = 'GROUP BY ' + @Group

     

        IF @Order <> ''

        BEGIN

            DECLARE @pos1 INT, @pos2 INT

            SET @Order = REPLACE(REPLACE(@Order, ' asc', ' ASC'), ' desc', ' DESC')

            IF CHARINDEX(' DESC', @Order) > 0

                IF CHARINDEX(' ASC', @Order) > 0

                BEGIN

                    IF CHARINDEX(' DESC', @Order) < CHARINDEX(' ASC', @Order)

                        SET @Operator = '<='

                    ELSE

                        SET @Operator = '>='

                END

                ELSE

                    SET @Operator = '<='

            ELSE

                SET @Operator = '>='

            SET @SortColumn = REPLACE(REPLACE(REPLACE(@Order, ' ASC', ''), ' DESC', ''), ' ', '')

            SET @pos1 = CHARINDEX(',', @SortColumn)

            IF @pos1 > 0

                SET @SortColumn = SUBSTRING(@SortColumn, 1, @pos1-1)

            SET @pos2 = CHARINDEX('.', @SortColumn)

            IF @pos2 > 0

            BEGIN

                SET @SortTable = SUBSTRING(@SortColumn, 1, @pos2-1)

                IF @pos1 > 0

                    SET @SortName = SUBSTRING(@SortColumn, @pos2+1, @pos1-@pos2-1)

                ELSE

                    SET @SortName = SUBSTRING(@SortColumn, @pos2+1, LEN(@SortColumn)-@pos2)

            END

            ELSE

            BEGIN

                SET @SortTable = @TableNames

                SET @SortName = @SortColumn

            END

        END

        ELSE

        BEGIN

            SET @SortColumn = @PrimaryKey

            SET @SortTable = @TableNames

            SET @SortName = @SortColumn

            SET @Order = @SortColumn

            SET @Operator = '>='

        END

     

        DECLARE @type varchar(50)

        DECLARE @prec int

        SELECT @type=t.name, @prec=c.prec

        FROM sysobjects o

        JOIN syscolumns c on o.id=c.id

        JOIN systypes t on c.xusertype=t.xusertype

        WHERE o.name = @SortTable AND c.name = @SortName

        IF CHARINDEX('char', @type) > 0

        SET @type = @type + '(' + CAST(@prec AS varchar) + ')'

     

        DECLARE @TopRows INT

        SET @TopRows = @PageSize * @CurrentPage + 1

        print @TopRows

        print @Operator

        EXEC('

            DECLARE @SortColumnBegin ' + @type + '

            SET ROWCOUNT ' + @TopRows + '

            SELECT @SortColumnBegin=' + @SortColumn + ' FROM  ' + @TableNames + ' ' + @Filter + ' ' + @Group + ' ORDER BY ' + @Order + '

            SET ROWCOUNT ' + @PageSize + '

            SELECT ' + @Fields + ' FROM  ' + @TableNames + ' ' + @Filter + ' AND ' + @SortColumn + '' + @Operator + '@SortColumnBegin ' + @Group + ' ORDER BY ' + @Order + '    

        ')   

    END

     

    GO

     

    --调用例子:

        --1.单表/单排序

        EXEC usp_PagingLarge 'bigtable','d_id','d_id,d_title,d_content,d_time',20,1,'','','d_id desc'

        --2.单表/多排序

        EXEC usp_PagingLarge 'bigtable','d_id','*',20,0,'','','d_time asc,d_id desc'

        --3.多表/单排序

        EXEC usp_PagingLarge 'bigtable left join bigtable_author on bigtable.d_id=bigtable_author.BigTable_id', 'bigtable.d_id', 'bigtable.d_id,bigtable.d_title,bigtable.d_content,bigtable.d_time,bigtable_author.d_author', 20, 0, '', '', 'bigtable.d_id asc'

        --4.多表/多排序

        EXEC usp_PagingLarge 'bigtable left join bigtable_author on bigtable.d_id=bigtable_author.BigTable_id', 'bigtable.d_id', 'bigtable.d_id,bigtable.d_title,bigtable.d_content,bigtable.d_time,bigtable_author.d_author', 20, 0, '', '', 'bigtable.d_time asc,bigtable.d_id desc'

    与自定义分页结合例子:

    http://bbs.blueidea.com/thread-2720032-1-1.html

    Create  Proc proc_PageRecordset

         @queryStr nvarchar(2000), --查询语句,用来获取要显示的数据必须满足的要求@keyField nvarchar (72), --主键

         @pageSize int--每页的行数@pageNumber int, --第几页

         @filter varChar(2000)='', --过滤,where后头的语句

         @order varChar(200)='' --排序方式AS

    BEGIN

    DECLARE @sqlText AS nvarchar(4000)

    DECLARE @sqlTable AS nvarchar(4000)

    DECLARE @sqlText_PageCount AS nvarchar(4000)

     

    set @filter=replace(@filter,'#','''')

     

    --这是最后一次所发现的bug,因为在排序中必须确定一个排出来的位置一样的table,不能让a在这次排第,那次又排第

    if CharIndex(@keyField,@order)=0

    Begin

         Set @order=@order+','+@keyField

    End

     

    if (Rtrim(@filter)='')

    begin

         SET @sqlTable = 'SELECT TOP ' + CAST((@pageNumber + 1) * @pageSize AS varchar(30)) + ' ' + @queryStr + ' ' + @order

         SET @sqlText_PageCount = 'Select Count(*) from (select ' +@queryStr+ ' ) as Table_temp'

    end

    else

    begin

         SET @sqlTable = 'SELECT TOP ' + CAST((@pageNumber + 1) * @pageSize AS varchar(30)) + ' ' + @queryStr + ' and ' + @filter + @order

         SET @sqlText_PageCount = 'Select Count(*) AS MyCount from (select ' +@queryStr+ ' and ' + @filter +' ) as Table_temp'

    end

    --譬如现在要第页数据,每页是行,那么现在要的数据就是在前行,并且不在原来的行内的

    SET @sqlText =

    'SELECT TOP ' + CAST(@pageSize AS varchar(30)) + ' * ' +

    'FROM (' + @sqlTable + ') AS tableA ' +

    'WHERE ' + @keyField + ' NOT IN(SELECT TOP ' +

    CAST(@pageNumber * @pageSize AS varchar(30)) + ' ' + @keyField +

    ' FROM (' + @sqlTable + ') AS tableB)'

     

    EXEC (@sqlText)

     

    exec (@sqlText_PageCount)

     

    END

     

    GO

    用SQLSERVER未公开的存储过程实现

     

    /**//****** 对象:  StoredProcedure [dbo].[SplitPage]    脚本日期: 04/23/2007 16:10:08 ******/

    SET ANSI_NULLS ON

    GO

    SET QUOTED_IDENTIFIER ON

    GO

    CREATE procedure [dbo].[SplitPage]

    (

        @SelectCommandText nvarchar(4000), -- 要执行的查询命令

       @CurrentPageIndex int = 0, -- 当前页的索引,从0 开始

        @PageSize int = 20, -- 每页的记录数

        @RowCount int = 0 out, -- 总的记录数

        @PageCount int = 0 out -- 总的页数

    )

    AS

     

    SET NOCOUNT ON

     

    DECLARE @p1 int

     

    SET @CurrentPageIndex = @CurrentPageIndex + 1

     

    EXEC    sp_cursoropen

            @p1 output,

            @SelectCommandText,

            @scrollopt = 1,

            @ccopt = 1,

            @RowCount = @RowCount output;

     

    SELECT @RowCount;

     

    SELECT @PageCount = ceiling(1.0 * @RowCount / @PageSize);

     

    SELECT @CurrentPageIndex = (@CurrentPageIndex - 1) * @PageSize + 1

     

    EXEC    sp_cursorfetch

            @p1,

            16,

            @CurrentPageIndex,

            @PageSize;

     

    EXEC    sp_cursorclose

            @p1

     

     调用方法:

     

    DECLARE    @return_value int,

            @RowCount int,

            @PageCount int

     

    EXEC    @return_value = [dbo].[SplitPage]

            @SelectCommandText = N'SELECT * FROM Log',

            @CurrentPageIndex = 0,

            @PageSize = 4,

            @RowCount = @RowCount OUTPUT,

            @PageCount = @PageCount OUTPUT

     

    SELECT    @RowCount as N'@RowCount',

            @PageCount as N'@PageCount'

     

    SELECT    'Return Value' = @return_value

     

    GO

    CSDN sqlserver 大版主zhoujian的存储过程

    /*--用存储过程实现的分页程序

     

    显示指定表、视图、查询结果的第X页

    对于表中主键或标识列的情况,直接从原表取数查询,其它情况使用临时表的方法

    如果视图或查询结果中有主键,不推荐此方法

     

     

    */

     

    /*--调用示例

    exec p_show '地区资料'

     

    exec p_show '地区资料',5,3,'地区编号,地区名称,助记码','地区编号'

    --*/

     

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_show]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)

    drop procedure [dbo].[p_show]

    GO

     

    CREATE Proc p_show

    @QueryStr nvarchar(4000), --表名、视图名、查询语句

    @PageSize int=10,    --每页的大小(行数)

    @PageCurrent int=1,    --要显示的页

    @FdShow nvarchar (4000)='', --要显示的字段列表,如果查询结果有标识字段,需要指定此值,且不包含标识字段

    @FdOrder nvarchar (1000)='' --排序字段列表

    as

    declare @FdName nvarchar(250) --表中的主键或表、临时表中的标识列名

    ,@Id1 varchar(20),@Id2 varchar(20) --开始和结束的记录号

    ,@Obj_ID int     --对象ID

    --表中有复合主键的处理

    declare @strfd nvarchar(2000) --复合主键列表

    ,@strjoin nvarchar(4000) --连接字段

    ,@strwhere nvarchar(2000) --查询条件

     

     

    select @Obj_ID=object_id(@QueryStr)

    ,@FdShow=case isnull(@FdShow,'') when '' then ' *' else ' '+@FdShow end

    ,@FdOrder=case isnull(@FdOrder,'') when '' then '' else ' order by '+@FdOrder end

    ,@QueryStr=case when @Obj_ID is not null then ' '+@QueryStr else ' ('+@QueryStr+') a' end

     

    --如果显示第一页,可以直接用top来完成

    if @PageCurrent=1

    begin

    select @Id1=cast(@PageSize as varchar(20))

    exec('select top '+@Id1+@FdShow+' from '+@QueryStr+@FdOrder)

    return

    end

     

    --如果是表,则检查表中是否有标识更或主键

    if @Obj_ID is not null and objectproperty(@Obj_ID,'IsTable')=1

    begin

    select @Id1=cast(@PageSize as varchar(20))

       ,@Id2=cast((@PageCurrent-1)*@PageSize as varchar(20))

     

    select @FdName=name from syscolumns where id=@Obj_ID and status=0x80

    if @@rowcount=0    --如果表中无标识列,则检查表中是否有主键

    begin

       if not exists(select 1 from sysobjects where parent_obj=@Obj_ID and xtype='PK')

        goto lbusetemp   --如果表中无主键,则用临时表处理

     

       select @FdName=name from syscolumns where id=@Obj_ID and colid in(

        select colid from sysindexkeys where @Obj_ID=id and indid in(

         select indid from sysindexes where @Obj_ID=id and name in(

          select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID

        )))

       if @@rowcount>1   --检查表中的主键是否为复合主键

       begin

        select @strfd='',@strjoin='',@strwhere=''

        select @strfd=@strfd+',['+name+']'

         ,@strjoin=@strjoin+' and a.['+name+']=b.['+name+']'

         ,@strwhere=@strwhere+' and b.['+name+'] is null'

         from syscolumns where id=@Obj_ID and colid in(

         select colid from sysindexkeys where @Obj_ID=id and indid in(

          select indid from sysindexes where @Obj_ID=id and name in(

           select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID

         )))

        select @strfd=substring(@strfd,2,2000)

         ,@strjoin=substring(@strjoin,5,4000)

         ,@strwhere=substring(@strwhere,5,4000)

        goto lbusepk

       end

    end

    end

    else

    goto lbusetemp

     

    /*--使用标识列或主键为单一字段的处理方法--*/

    lbuseidentity:

    exec('select top '+@Id1+@FdShow+' from '+@QueryStr

       +' where '+@FdName+' not in(select top '

     +@Id2+' '+@FdName+' from '+@QueryStr+@FdOrder

       +')'+@FdOrder

       )

    return

     

    /*--表中有复合主键的处理方法--*/

    lbusepk: 

    exec('select '+@FdShow+' from(select top '+@Id1+' a.* from

       (select top 100 percent * from '+@QueryStr+@FdOrder+') a

       left join (select top '+@Id2+' '+@strfd+'

       from '+@QueryStr+@FdOrder+') b on '+@strjoin+'

       where '+@strwhere+') a'

       )

    return

     

    /*--用临时表处理的方法--*/

    lbusetemp: 

    select @FdName='[ID_'+cast(newid() as varchar(40))+']'

    ,@Id1=cast(@PageSize*(@PageCurrent-1) as varchar(20))

    ,@Id2=cast(@PageSize*@PageCurrent-1 as varchar(20))

     

    exec('select '+@FdName+'=identity(int,0,1),'+@FdShow+'

       into #tb from'+@QueryStr+@FdOrder+'

    select '+@FdShow+' from #tb where '+@FdName+' between '

    +@Id1+' and '+@Id2

    )

     

    GO

  • 相关阅读:
    delphi AlphaControls
    MATLAB 中NORM运用
    matlab画图形函数 semilogx
    fir2(n,f,m)
    离散系统频响特性函数freqz()
    snr ber Eb/N0之间的区别与联系
    MATLAB中白噪声的WGN和AWGN函数的使用
    matlab 功率谱分析
    用matlab实现同一个序列重复N倍
    Stem函数绘图
  • 原文地址:https://www.cnblogs.com/mikelij/p/1779873.html
Copyright © 2011-2022 走看看