免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3622 | 回复: 0
打印 上一主题 下一主题

ASP.NET针对Sybase数据库使用分页技术 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-06-03 17:37 |只看该作者 |倒序浏览
转:默默ASP.NET
ASP.NET针对Sybase数据库使用分页技术

在编写一个通用数据库操作接口的分页查询时,发现MS SQL Server、Oracle、MySql、Access等数据库都有分页查询语句,只有Sybase没有,如果用AseDataAdapter.Fill(dataSet, startRowIndex, maximumRows, "item")方法实现,实际上还是将数据库的所有记录返回的,这样在数据量很大(超过10万条记录)时,速度将无法忍受,经过互联网搜索,发现Sybase 15后加入了Top子句,经测试后发现Top不能使用在子句中,效果与set rowcount一样不能实现分页,如果有哪位大虾知道其语法请予以赐教,搜索中还找到一个分页查询的存储过程,代码如下:
create procedure test_p @ipage int, @num int as   /* @ipage 页码, @num 每页的记录数 */
  1. begin
  2.          declare @maxpages int, @rcount int   /* @maxpages 最大页码 */
  3.          if @ipage>=100
  4.                    select @maxpages=ceiling(count(*)/@num) from test
  5.          else
  6.           select @maxpages=100000
  7.          if @ipage<=@maxpages/2
  8.          begin
  9.                    select @rcount=@ipage*@num
  10.                    set rowcount @rcount
  11.                    select id=identity(12),name,descs,ddd into #temptable1 from test order by id
  12.                    select * from #temptable1 where id>=(@ipage-1)*@num and id<= @ipage*@num
  13.          end
  14.          else
  15.          begin
  16.                    select @rcount=(@maxpages-@ipage+1)*@num
  17.                    set rowcount @rcount
  18.                    select id=identity(12),name,descs,ddd into #temptable2 from test order by id desc
  19.                    select id,name, ddd,descs from #temptable2 where id>=(@maxpages-@ipage)*@num and id<= (@maxpages-@ipage+1)*@num order by id desc
  20.          end
  21. end
  22. 后有好心人更改为一个通用版本,代码如下:
  23. create procedure splitpage @qry varchar(16384),@ipage int, @num int as   /*@qry SQL语句, @ipage 页数, @num 每页记录条数 */
  24. begin
  25.          declare @maxpages int
  26.          declare @rcount int
  27.          declare @execsql varchar(16384)
  28.         
  29.          if @ipage>=100
  30.                    select @maxpages=ceiling(count(*)/@num) from test
  31.          else
  32.                    select @maxpages=100000
  33.          if @ipage<=@maxpages/2
  34.          begin
  35.                    select @rcount=@ipage*@num
  36.                    set rowcount @rcount
  37.                    set @execsql = stuff(@qry,charindex('select',@qry),6,'select sybid=identity(12),')
  38.                    set @execsql = stuff(@execsql, charindex('from',@execsql),4,'into #temptable1 from')
  39.                    set @execsql = @execsql || ' select * from #temptable1 where sybid>' || convert(varchar,(@ipage-1)*@num) || ' and sybid <= ' || convert(varchar,@ipage*@num)
  40.                    execute (@execsql)
  41.          end
  42.          else
  43.          begin
  44.                    select @rcount=(@maxpages-@ipage+1)*@num
  45.                    set rowcount @rcount
  46.                    set @execsql = stuff(@qry,charindex('select',@qry),6,'select sybid=identity(12),')
  47.                    set @execsql = stuff(@execsql, charindex('from',@execsql),4,'into #temptable1 from')
  48.                    set @execsql = @execsql || ' order by sybid desc'
  49.                    set @execsql = @execsql || ' select * from #temptable1 where sybid > ' || convert(varchar,(@maxpages-@ipage)*@num) || ' and sybid <= ' || convert(varchar,(@maxpages-@ipage+1)*@num)
  50.                    execute (@execsql)
  51.          end
  52. end
复制代码
使用中发现几个问题:
Ø SQL语句中不能有排序子句;
Ø 查询表中不能用Identity;
Ø 分页计算存在问题。
我对该存储过程进行了修改,代码如下:
/****************************************************************/
/*   对于大于maxrow条的数据表,排序参数不要为空,               */
/*   在查询后一半页数时,排序参数使用倒序                       */
/*   对于有自增量字段的数据表,自增量字段名称参数不能为空,     */
/*   此时排序参数无效,排序按自增量字段进行排序                 */
/****************************************************************/
--drop proc splitpage
create procedure splitpage
@fieldclause varchar(8042), --字段
@tableclause varchar(100),   --表名
@whereclause varchar(8042), --条件
@sortclause varchar(180),    --排序
@identityname varchar(20),   --自增量字段名称
@ipage int,                  --需要查询页数
@num int,                    --每页条数
@totalrow int,               --该查询语句结果的总记录数
@maxrow int                  --数据表总行数超过此参数后,在查询后一半页数时,排序参数使用倒序
as
  1. begin
  2.          declare @maxpages int   --总页数
  3.          declare @rcount int     --查询的记录数
  4.          declare @bottomstart int    --从后面查询标志,0-从上查询;1-从下查询
  5.          declare @execsql varchar(16384)   --SQL语句
  6.          declare @remainder int --计算数据表总条数的余数变量
  7.         
  8.          select @rcount=@ipage*@num
  9.          select @remainder=@totalrow % @num
  10.          select @maxpages=ceiling(@totalrow/@num)+1
  11.          if @totalrow>@maxrow
  12.          begin
  13.                    if @ipage>@maxpages/2
  14.                    begin
  15.                             select @bottomstart = 1
  16.                    end
  17.                    else
  18.                    begin
  19.                    select @bottomstart = 0
  20.                    end
  21.          end
  22.          else
  23.          begin
  24.                    select @bottomstart = 0
  25.          end
  26.         
  27.          if @identityname=''
  28.          begin
  29.                    select @execsql = 'select sybid=identity(12),' || @fieldclause || ' into #moy_temptable from ' || @tableclause
  30.          end
  31.          else
  32.          begin
  33.                    select @execsql = 'select 100000000000 sybid,' || @fieldclause || ' into #moy_temptable from ' || @tableclause
  34.                    select @bottomstart = 0
  35.          end
  36.         
  37.          if @bottomstart = 0
  38.          begin
  39.                    set rowcount @rcount
  40.          end
  41.          else
  42.          begin
  43.                    select @rcount=(@maxpages-@ipage+1)*@num
  44.                    set rowcount @rcount
  45.          end
  46.         
  47.          if @whereclause<>''
  48.          begin
  49.                    select @execsql = @execsql || ' where ' || @whereclause
  50.          end
  51.          if @sortclause<>''
  52.          begin
  53.                    if @identityname=''
  54.                    begin
  55.                             select @execsql = @execsql || ' order by ' || @sortclause
  56.                    end
  57.                    else
  58.                    begin
  59.                             select @execsql = @execsql || ' order by ' || @identityname
  60.                    end
  61.          end
  62.         
  63.          if @identityname<>''
  64.          begin
  65.                    select @execsql = @execsql || ' update #moy_temptable set sybid=(select count(1) from #moy_temptable b where a.' || @identityname || '>=b.' || @identityname || ') from #moy_temptable a'
  66.          end
  67.         
  68.          if @bottomstart = 0
  69.          begin
  70.                    select @execsql = @execsql || ' select ' || @fieldclause ||' from #moy_temptable where sybid>' || convert(varchar,(@ipage-1)*@num) || ' and sybid <= ' || convert(varchar,@ipage*@num)
  71.          end
  72.          else
  73.          begin
  74.                    select @execsql = @execsql || ' select ' || @fieldclause ||' from #moy_temptable where sybid <= ' || convert(varchar,(@maxpages-@ipage)*@num+@remainder) || ' and sybid > ' || convert(varchar,(@maxpages-(@ipage+1))*@num+@remainder)
  75.          end
  76.          execute (@execsql)
  77.          set rowcount 0
  78. end
  79. 下面是ASP.NET(C#)对该存储过程的调用,代码如下:
  80.         private DataTable GetDataTable(string fieldClause, string tableClause, string whereClause,
  81.             string sortClause, string identityName, int pageIndex, int pageNum, int totalRowCount)
  82.         {
  83.             connection.Open();
  84.             try
  85.             {
  86.                 command.CommandType = CommandType.StoredProcedure;
  87.                 command.CommandText = "splitpage";
  88.                 AseParameterCollection parameters = (AseParameterCollection)command.Parameters;
  89.                 parameters.Add("@fieldclause", AseDbType.VarChar, 8042).Value = fieldClause;
  90.                 parameters.Add("@tableclause", AseDbType.VarChar, 100).Value = tableClause;
  91.                 parameters.Add("@whereclause", AseDbType.VarChar, 8042).Value = whereClause;
  92.                 parameters.Add("@sortclause", AseDbType.VarChar, 180).Value = sortClause;
  93.                 parameters.Add("@identityname", AseDbType.VarChar, 20).Value = identityName;
  94.                 parameters.Add("@ipage", AseDbType.Integer).Value = pageIndex;
  95.                 parameters.Add("@num", AseDbType.Integer).Value = pageNum;
  96.                 parameters.Add("@totalrow", AseDbType.Integer).Value = totalRowCount;
  97.                 parameters.Add("@maxrow", AseDbType.Integer).Value = MaxRowInversionSortNum;
  98.                 AseDataAdapter dataAdapter = new AseDataAdapter((AseCommand)command);
  99.                 DataSet dataSet = new DataSet();
  100.                 dataAdapter.Fill(dataSet, "item");
  101.                 DataTable dataTable = dataSet.Tables["item"];
  102.                 return dataTable;
  103.             }
  104.             finally
  105.             {
  106.                 connection.Close();
  107.             }
  108.         }
  109.         private List<T> GetInfos<T>(DataTable dataTable, bool isPageOverHalf) where T:IBaseClass,new ()
  110.         {
  111.             List<T> result = new List<T>();
  112.             T data=new T();
  113.             if (isPageOverHalf)
  114.             {
  115.                 for (int num = dataTable.Rows.Count - 1; num >= 0; num--)
  116.                {
  117.                     data = (T)data.GetInfo(dataTable.Rows[num]);
  118.                     result.Add(data);
  119.                 }
  120.             }
  121.             else
  122.             {
  123.                 foreach (DataRow dataRow in dataTable.Rows)
  124.                 {
  125.                     data = (T)data.GetInfo(dataRow);
  126.                     result.Add(data);
  127.                 }
  128.             }
  129.             return result;
  130.         }
复制代码
值得注意的是在从下查询时,应该从后向前添加到记录集中,通过下面的函数获取页码及从下查询标志的信息:
  1.    private void GetPageInfo(int totalRowCount, int startRowIndex, int maximumRows, out bool isPageOverHalf, out int pageIndex)
  2.         {
  3.             pageIndex = (startRowIndex + maximumRows) / maximumRows;
  4.             if (totalRowCount <= MaxRowInversionSortNum)
  5.             {
  6.                 isPageOverHalf = false;
  7.                 return;
  8.             }
  9.             decimal dTotalRowCount = (decimal)totalRowCount;
  10.             decimal dPageNum = (decimal)maximumRows;
  11.             decimal pageCount = Math.Ceiling(dTotalRowCount / dPageNum);
  12.             decimal pageHalf = Math.Ceiling(pageCount / (decimal)2);
  13.             if (pageIndex > pageHalf)
  14.             {
  15.                 isPageOverHalf = true;
  16.             }
  17.             else
  18.             {
  19.                 isPageOverHalf = false;
  20.             }
  21.         }
复制代码
所需表的建表脚本:
  1. alter table test_detail
  2.   drop constraint FK_TEST_DET_REFERENCE_TEST_MAI
  3. go
  4. if exists (select 1
  5.             from sysobjects
  6.            where id = object_id('test_detail')
  7.             and   type = 'U')
  8.    drop table test_detail
  9. go
  10. if exists (select 1
  11.             from sysobjects
  12.            where id = object_id('test_main')
  13.             and   type = 'U')
  14.    drop table test_main
  15. go
  16. /*==============================================================*/
  17. /* Table: test_detail                                           */
  18. /*==============================================================*/
  19. create table test_detail (
  20.    detail_id            integer              identity,
  21.    main_id              integer              null,
  22.    detail_name          char(10)             not null,
  23.    constraint PK_TEST_DETAIL primary key (detail_id)
  24. )
  25. go
  26. /*==============================================================*/
  27. /* Table: test_main                                             */
  28. /*==============================================================*/
  29. create table test_main (
  30.    main_id              integer              not null,
  31.    main_name            char(10)             not null,
  32.    constraint PK_TEST_MAIN primary key (main_id)
  33. )
  34. go
  35. alter table test_detail
  36.    add constraint FK_TEST_DET_REFERENCE_TEST_MAI foreign key (main_id)
  37.       references test_main (main_id)
  38. go
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP