zoukankan      html  css  js  c++  java
  • ASP.Net + SQL Server 存储过程实现分页排序

    问题提出:

    在应用程序中经常需要查询数据。当查询结果数据量比较大的时候,检索结果、界面显示都需要花费大量的时间。为了避免这个问题,应该每次只检索部分数据,也就是使用常见的分页方式来处理。分页的问题在asp.net中好像非常简单,只要在GridView中启用分页就可以了。启用分页后,GridView关联数据源控件,依旧会加载所有的数据。这个解决方法只是“掩耳盗铃” ,会导致在大数据量的情况下导致查询的效率变低。

    解决方法:

    使用GridView的自定义分页功能。使用自定义分页功能需要实现两个逻辑:得到结果集的总数、查找自定范围的数据。

    GridView 分页实现,可以参考 Scott Mitchell 文章 Efficiently Paging Through Large Amounts of Data

    本文组要介绍如何在使用SQL Server 实现排序获取分页数据。

    1、使用子查询+TOP关键字方式

    if object_id('GetStudentPaged') is not null
        drop procedure GetStudentPaged;
    go
    /************************************
    * 描述: 查找指定范围的记录
    * 参数:@startRow 其实记录
    *           @maximumRows 最大的记录数量
    *************************************/

    create procedure GetStudentPaged
        @startRow int,
        @maxmimumRows int
    as
    select top (@maxmimumRows) * from Student
    where StudentId NOT IN( select top(@startRow) StudentId from Student )
    go

    如果需要按条件查找,条件可能会有所不同。通过参数将where条件传入到存储过程中。由于where子句不支持使用变量,所以需要将在存储过程中组合SQL语句,通过动态SQL方式执行。

    create procedure GetStudentPaged
        @startRow int,
        @maxmimumRows int,
        @whereExpression nvarchar(512)
    as
    --存储SQL语句的字符串
    declare @sql nvarchar(max)

    set @sql = N'Select Top(' + ltrim(str(@maxmimumRows)) + N') * '
    set @sql = @sql + N' from Student where '

    --判断是否有查询条件
    if @whereExpression is not null and @whereExpression <> N''
    begin
       set @sql = @sql + @whereExpression + N' and '
    end

    set @sql = @sql + N'StudentId NOT IN ('
    set @sql = @sql + N'Select Top('+ ltrim(str(@startRow)) + ') StudentId from Student '

    if @whereExpression is not null and @whereExpression <> N''
    begin
       set @sql = @sql + N' where ' + @whereExpression
    end
    set @sql = @sql + ')'

    --print @sql
    execute sp_executesql @sql

    go

    现在就能在条件检索的情况下也实现分页了。下面的问题是,如果使用GridView时需要支持排序功能,那么还需要添加对排序的支持。其实这个问题就比较简单了,只要增加一个排序参数就可以了。

    create procedure GetStudentPaged
        @startRow int,
        @maxmimumRows int,
        @whereExpression nvarchar(512),
        @sortExpression nvarchar(512)
    as
    --存储SQL语句的字符串
    declare @sql nvarchar(max)

    set @sql = N'Select Top(' + ltrim(str(@maxmimumRows)) + N') * '
    set @sql = @sql + N' from Student where '

    --判断是否有查询条件
    if @whereExpression is not null and @whereExpression <> N''
    begin
       set @sql = @sql + @whereExpression + N' and '
    end

    set @sql = @sql + N'StudentId NOT IN ('
    set @sql = @sql + N'Select Top('+ ltrim(str(@startRow)) + ') StudentId from Student '

    if @whereExpression is not null and @whereExpression <> N''
    begin
       set @sql = @sql + N' where ' + @whereExpression
    end

    if @sortExpression is not null and @sortExpression <> N''
    begin
       set @sql = @sql + N' order by ' + @sortExpression
    end

    set @sql = @sql + ')'

    if @sortExpression is not null and @sortExpression <> N''
    begin
       set @sql = @sql + N' order by ' + @sortExpression
    end

    --print @sql
    execute sp_executesql @sql

    go

    这里给出我使用Student表定义

    create table Student (
       StudentId            uniqueidentifier     not null,
       Name                 varchar(128)         not null,
       Sex                  bit                  not null,
       BirthDate            datetime             not null,
       Nation               varchar(128)         not null,
       NativePlace          varchar(128)         not null,
       Address              varchar(256)         null,
       Photo                image                null,
       Memo                 varchar(512)         null,
       StudentStatus        varchar(56)          null
    )
    go

    使用T-SQL产生大量数据

    declare @i int
    set @i = 0;
    while(@i<10000)
    begin
      insert into Student(StudentId,[Name],Sex,BirthDate,
          Nation,NativePlace,[Address],Photo,Memo,StudentStatus)
         values(NewId(),'Rain' + str(@i),floor(rand(2)),DateAdd(year,-10,getdate()),'汉族','四川','Now address',null,'test','在读')
      set @i = @i + 1
    end

    2、使用临时表实现

    根据筛选、排序条件将符合条件的数据保存到临时表,并在临时表中增加一个自动增长的辅助列,用于获取指定范围的数据。

    use TeachMis;
    go

    if object_id('GetStudentPaged') is not null
        drop procedure GetStudentPaged;
    go


    create procedure GetStudentPaged
        @startRow int,
        @maxmimumRows int,
        @whereExpression nvarchar(512),
        @sortExpression nvarchar(512)
    as

    if (object_id('tempdb..#Student') is not null)
        drop table #Student;
    go

    --产生没有记录的临时表
    SELECT identity(int,1,1) as RowId
    ,[StudentId]
    ,[Name]
    ,[Sex]
    ,[BirthDate]
    ,[Nation]
    ,[NativePlace]
    ,[Address]
    ,[Photo]
    ,[Memo]
    ,[StudentStatus]
    into #Student
    FROM [Student] where 1=0

    declare @sql nvarchar(max)
    set @sql = 'insert into #Student
    SELECT
    [StudentId]
    ,[Name]
    ,[Sex]
    ,[BirthDate]
    ,[Nation]
    ,[NativePlace]
    ,[Address]
    ,[Photo]
    ,[Memo]
    ,[StudentStatus]
    FROM [Student]'

    if @whereExpression is not null and @whereExpression <> ''
    begin
        set @sql = @sql + ' where ' + @whereExpression
    end

    if @sortExpression is not null and @sortExpression <> ''
    begin
      set @sql = @sql + 'order by ' + @sortExpression
    end

    execute sp_executesql @sql

    select
    [StudentId]
    ,[Name]
    ,[Sex]
    ,[BirthDate]
    ,[Nation]
    ,[NativePlace]
    ,[Address]
    ,[Photo]
    ,[Memo]
    ,[StudentStatus]
    from #Student
    where RowId between @startRow and @startRow + @maximumRows -1
    order by RowId

    go

    3.使用 SQL Server 2005 的 CTE 表达式实现。

    具体可以参考 Scott Mitchell 文章 Efficiently Paging Through Large Amounts of Data

  • 相关阅读:
    (转)kubernetes更新操作详解--kubectl apply
    awk做统计和计算平均值
    kvm虚拟化
    容器(转
    使用python3来实现简易web服务
    12306接口
    python3中的venv环境
    markdown 插入表格
    面向对象编程——类(class)2
    开发纯ndk程序之环境搭配
  • 原文地址:https://www.cnblogs.com/kodong/p/1154928.html
Copyright © 2011-2022 走看看