`
bdk82924
  • 浏览: 562855 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

转:ASE中数据结果集分页功能的三种实现方法 .

 
阅读更多

转:http://blog.csdn.net/andkylee/article/details/5638033

 

本篇介绍三种方法。

 

第一种:利用游标

程序开发人员比较喜欢使用游标,因为游标的“循环”遍历方式类似编程语言中的for,while,loop语句的实现方法,写起来比较容易。使用游标一般步骤是:为指定的SQL语句定义一个游标,打开并移动游标,当移动到指定行号的记录行之后,再按照需要提取的行数来取数据。从表面上看解决了提取指定范围数据的问题;但是在实际应用 上,有可能会出现严重的性能问题。建立游标需要耗用一定的系统资源之外;当表内的数据量有上千万甚至到亿级别并且需要取大量的数据结果时,用游标每移动一次就取这行数据,然后再移动游标,这个过程将是缓慢的。在使用游标的过程中,系统会给相应的表加上共享锁,导致锁竞争而严重影响数据库的性能。

 

在此不再介绍游标的实现方式,此法比较简单。

 

第二种:利用临时表和标志列

 

在Sybase ASE12.5.3及以后的版本中,我们可以用top关键字来限定只返回结果集的前N行数据。在ASE12.5.3之前的版本中只能用set rowcount N 的方法来“曲线救国”了。

对于取结果集的第N行至第N+M行数据的要求,我们考虑利用top来实现的话,比较容易想到的是:执行两次top,再加l两次倒序排序。

步骤如下:

       (1) select top N+M * from table_name where_clause order by ID     把此结果集派生为表:table_name1

                  (2)   select top M * from table_name1 order by ID  DESC   把此结果集派生为表:table_name2

                  (3)   select * from table_name2 order by ID  DESC

上面的3条语句好像能够实现返回第N行至第N+M行数据的要求。但是,在Sybase ASE中仅仅利用派生表而不利用临时表是不能实现这个要求的。

仅仅是ASE中的“派生出派生表(derived table)的SQL语句中不能含有order by 子句”这个限制就足以使上面的方法行不通。还有一个限制是,上面的3个步骤中都利用ID列进行排序。如果表中没有可用的排序列时,那么上述方法也不能用了。不过幸运的是,一般要求对其结果集进行分页的表都是有可以用作排序的列的(数字型或者日期型)。

 

继续寻找一个能用的方法,下面着重介绍目前通用的ASE的分页思路。此思路的关键是产生identity自增列和临时表。

在ASE中大家要是找到了不用临时表就可以实现分页的方法请麻烦告诉我一声。 我尝试了很多次,都不是很理想。

 

概括起来主要语句有两条:

           (1)   select syb=identity(10),*  into #temp_table from table_name where_clause   order_by_clause

           (2)   select  * from #temp_table where_clause and syb >= N   and syb <= N+M

 

用一个例子演示一下:

(1) 建立测试表:testA

 

  1. create table testA(id int not null,name varchar(30) null)  
  2. go  

 

 

(2) 插入测试数据

 

  1. insert into testA  
  2. select 1,'liuzhenfu'  
  3. go  
  4. insert into testA  
  5. select 2,'andkylee'  
  6. go  

 

 

(3) 循环插入大量的重复数据,

 

  1. insert into testA  
  2. select id+(select max(id) from testA),name from testA  
  3. go 15  

 

向表testA循环插入已有的数据,15次之后,表testA内的数据达到2^16 = 65536 行。

 

(4) 利用临时表 + 自增标志列来提取第100行至第200行的数据。

语句如下:

select syb=identity(10) ,* into #tempA from testA

select * from #tempA where syb>=100 and syb<=200

drop table #tempA

返回的结果为:

 

  1. 1> select syb=identity(10),* into #tempA from testA  
  2. 2> select * from #tempA where syb>=100 and syb<=200  
  3. 3> go  
  4. (65536 rows affected)  
  5.  syb           id          name  
  6.  ------------- ----------- ---------------------------  
  7.            100         100 andkylee  
  8.            101         101 liuzhenfu  
  9.            102         102 andkylee  
  10.            103         103 liuzhenfu  
  11.            104         104 andkylee  
  12.            105         105 liuzhenfu  
  13.            106         106 andkylee  
  14.            107         107 liuzhenfu  
  15.            108         108 andkylee  
  16.            109         109 liuzhenfu  
  17.            110         110 andkylee  
  18.            111         111 liuzhenfu  
  19.            112         112 andkylee  
  20.            113         113 liuzhenfu  
  21.            114         114 andkylee  
  22.            115         115 liuzhenfu  
  23.            116         116 andkylee  
  24.            117         117 liuzhenfu  
  25.            118         118 andkylee  
  26.            119         119 liuzhenfu  
  27.            120         120 andkylee  
  28.            121         121 liuzhenfu  
  29.            122         122 andkylee  
  30.            123         123 liuzhenfu  
  31.            124         124 andkylee  
  32.            125         125 liuzhenfu  
  33.            126         126 andkylee  
  34.            127         127 liuzhenfu  
  35.            128         128 andkylee  
  36.            129         129 liuzhenfu  
  37.            130         130 andkylee  
  38.            131         131 liuzhenfu  
  39.            132         132 andkylee  
  40.            133         133 liuzhenfu  
  41.            134         134 andkylee  
  42.            135         135 liuzhenfu  
  43.            136         136 andkylee  
  44.            137         137 liuzhenfu  
  45.            138         138 andkylee  
  46.            139         139 liuzhenfu  
  47.            140         140 andkylee  
  48.            141         141 liuzhenfu  
  49.            142         142 andkylee  
  50.            143         143 liuzhenfu  
  51.            144         144 andkylee  
  52.            145         145 liuzhenfu  
  53.            146         146 andkylee  
  54.            147         147 liuzhenfu  
  55.            148         148 andkylee  
  56.            149         149 liuzhenfu  
  57.            150         150 andkylee  
  58.            151         151 liuzhenfu  
  59.            152         152 andkylee  
  60.            153         153 liuzhenfu  
  61.            154         154 andkylee  
  62.            155         155 liuzhenfu  
  63.            156         156 andkylee  
  64.            157         157 liuzhenfu  
  65.            158         158 andkylee  
  66.            159         159 liuzhenfu  
  67.            160         160 andkylee  
  68.            161         161 liuzhenfu  
  69.            162         162 andkylee  
  70.            163         163 liuzhenfu  
  71.            164         164 andkylee  
  72.            165         165 liuzhenfu  
  73.            166         166 andkylee  
  74.            167         167 liuzhenfu  
  75.            168         168 andkylee  
  76.            169         169 liuzhenfu  
  77.            170         170 andkylee  
  78.            171         171 liuzhenfu  
  79.            172         172 andkylee  
  80.            173         173 liuzhenfu  
  81.            174         174 andkylee  
  82.            175         175 liuzhenfu  
  83.            176         176 andkylee  
  84.            177         177 liuzhenfu  
  85.            178         178 andkylee  
  86.            179         179 liuzhenfu  
  87.            180         180 andkylee  
  88.            181         181 liuzhenfu  
  89.            182         182 andkylee  
  90.            183         183 liuzhenfu  
  91.            184         184 andkylee  
  92.            185         185 liuzhenfu  
  93.            186         186 andkylee  
  94.            187         187 liuzhenfu  
  95.            188         188 andkylee  
  96.            189         189 liuzhenfu  
  97.            190         190 andkylee  
  98.            191         191 liuzhenfu  
  99.            192         192 andkylee  
  100.            193         193 liuzhenfu  
  101.            194         194 andkylee  
  102.            195         195 liuzhenfu  
  103.            196         196 andkylee  
  104.            197         197 liuzhenfu  
  105.            198         198 andkylee  
  106.            199         199 liuzhenfu  
  107.            200         200 andkylee  
  108. (101 rows affected)  

 

 

需要将select * from #tempA中的星号*替换为需要返回的列名。

 

继续。。。。

 

当要求返回满足name='andkylee'的所有行中的第100行至第200行的数据时, 利用

select syb=identity(10),* into #tempA from testA where name='andkylee'

select * from #tempA where syb>=100 and syb<=200

 

drop table #tempA

 

 

 

第三种:利用rowcount

此种方法有点不足:必须利用可用作排序的列 对结果集进行排序。

还是上面的测试表testA,如果从第9000行开始选择10行数据,那么语句如下:

declare @id1 int
set rowcount 9000
select @id1 = id from testA order by id
set rowcount 10
select *from testA where id >= @id1 order by id
set rowcount 0
go

 

此种方法中核心语句是select @id1=id from testA order by id , 在对表testA执行查询的过程中,每读取一行都会把id列的值赋给@id1这个变量,一直持续到最后一行,@id1这个变量反复被下一行的id值刷新,结果只得到最后一样的id值。如果在此select语句之前加上rowcount的限定,那么就可用使得@id1这个变量获得第rowcount行的id值,那么我们也就获得了返回范围结果集的起点了。

后面的 set rowcount 10

         select * from testA where id >= @id1 order by id

这两句实际上可以用一句select top 10 * from testA where id >= @id1 order by id  来替代。 

 

这样,两种不同的实现形式为:

declare @id1 int
set rowcount 9000
select @id1 = id from testA  order by id
set rowcount 0
select top 10  *from testA where  id >= @id1 order by id
go

 

分别看看执行结果吧。

 

  1. 1> declare @id1 int  
  2. 2> set rowcount 9000  
  3. 3> select @id1 = id from testA order by id  
  4. 4> set rowcount 10  
  5. 5> select *from testA where id >= @id1 order by id  
  6. 6> set rowcount 0  
  7. 7> go  
  8. (9000 rows affected)  
  9.  id          name  
  10.  ----------- ------------------------------  
  11.         9000 andkylee  
  12.         9001 liuzhenfu  
  13.         9002 andkylee  
  14.         9003 liuzhenfu  
  15.         9004 andkylee  
  16.         9005 liuzhenfu  
  17.         9006 andkylee  
  18.         9007 liuzhenfu  
  19.         9008 andkylee  
  20.         9009 liuzhenfu  
  21. (10 rows affected)  
  22. 1>  

 

第二种方式的结果:

 

  1. 1> declare @id1 int  
  2. 2> set rowcount 9000  
  3. 3> select @id1 = id from testA order by id  
  4. 4> set rowcount 0  
  5. 5> select top 10  *from testA where id >= @id1 order by id  
  6. 6> go  
  7. (9000 rows affected)  
  8.  id          name  
  9.  ----------- ------------------------------  
  10.         9000 andkylee  
  11.         9001 liuzhenfu  
  12.         9002 andkylee  
  13.         9003 liuzhenfu  
  14.         9004 andkylee  
  15.         9005 liuzhenfu  
  16.         9006 andkylee  
  17.         9007 liuzhenfu  
  18.         9008 andkylee  
  19.         9009 liuzhenfu  
  20. (10 rows affected)  
  21. 1>  

 

当然,两种结果一模一样。

 

 

最后我们测试表testA中的ID列顺序值打乱, 来看看以上语句的执行情况。执行:

 

  1. update testA set id = id + cast( rand() * 65536 as int )    

 

 

ID列值打乱之后,前100行的数据为:

 

  1. 1> select top 100 * from testA  
  2. 2> go  
  3.  id          name  
  4.  ----------- ------------------------------  
  5.        51366 liuzhenfu  
  6.        33573 andkylee  
  7.        19447 liuzhenfu  
  8.        19408 andkylee  
  9.        57839 liuzhenfu  
  10.        18817 andkylee  
  11.      ......................  
  12.        19075 liuzhenfu  
  13.        17081 andkylee  
  14.        26444 liuzhenfu  
  15.         6620 andkylee  
  16.        52344 liuzhenfu  
  17.        49348 andkylee  
  18. (100 rows affected)  

 

 

 

我们要求返回满足name='andkylee'的从第9000行开始的10行数据。

declare @id1 int
set rowcount 9000
select @id1 = id from testA where name='andkylee' order by id
set rowcount 10
select *from testA where name='andkylee' and id >= @id1 order by id
set rowcount 0
go

 

结果为:

 

  1. 1> declare @id1 int  
  2. 2> set rowcount 9000  
  3. 3> select @id1 = id from testA where name='andkylee' order by id  
  4. 4> set rowcount 10  
  5. 5> select *from testA where name='andkylee' and id >= @id1 order by id  
  6. 6> set rowcount 0  
  7. 7> go  
  8. (9000 rows affected)  
  9.  id          name  
  10.  ----------- ------------------------------  
  11.        48639 andkylee  
  12.        48639 andkylee  
  13.        48641 andkylee  
  14.        48641 andkylee  
  15.        48642 andkylee  
  16.        48643 andkylee  
  17.        48644 andkylee  
  18.        48644 andkylee  
  19.        48650 andkylee  
  20.        48650 andkylee  
  21. (10 rows affected)  

 

 

 

如果不对ID列进行排序, 有下面的sql语句:

declare @id1 int
set rowcount 9000
select @id1 = id from testA where name='andkylee'
set rowcount 10
select *from testA where name='andkylee' and id >= @id1 
set rowcount 0
go

 

相应的结果集为:

 

  1. 1> declare @id1 int  
  2. 2> set rowcount 9000  
  3. 3> select @id1 = id from testA where name='andkylee'  
  4. 4> set rowcount 10  
  5. 5> select *from testA where name='andkylee' and id >= @id1  
  6. 6> set rowcount 0  
  7. 7> go  
  8. (9000 rows affected)  
  9.  id          name  
  10.  ----------- ------------------------------  
  11.        74076 andkylee  
  12.        74514 andkylee  
  13.        74053 andkylee  
  14.        74385 andkylee  
  15.        74339 andkylee  
  16.        74792 andkylee  
  17.        74794 andkylee  
  18.        74984 andkylee  
  19.        75052 andkylee  
  20.        74138 andkylee  
  21. (10 rows affected)  
  22. 1>  

 

 

可以发现这个两句的结果是不同的。

 

我想既然都要求返回指定范围的结果集, 肯定是有排序的依据了, 否则怎么知道该返回哪个范围呢?

 

还有,我给出的第三种方法,在进行表扫描的时候,即使不指定排序,也是能够得到正确结果的。因为表扫描时很可能会按照表内数据在物理页面上的物理位置来返回结果。

分享到:
评论

相关推荐

    unity插件ASE(Amplify Shader Editor 1.8.9.035)

    通过ASE插件,Unity开发者可以更轻松地实现复杂的图形效果,比如屏幕空间反射、体积光照、次表面散射等高级技术,而不需要深入研究底层的图形学原理。同时,ASE的易用性和灵活性也使得它成为Unity项目中提升图形质量...

    unity插件ASE(1.8.9.035)

    Unity插件ASE,全称Amplify Shader Editor,是一个强大的Unity专用水晶 shader 编辑器,版本号1.8.9.035。它为Unity开发人员提供了一个...通过熟练掌握ASE,你可以在游戏中实现独特的视觉效果,提升整体的用户体验。

    Python库 | ase-3.16.0.tar.gz

    5. **数据分析和可视化**:ASE提供了分析和可视化工具,如轨迹分析、能量分布计算、结构优化后的几何形状展示等,便于用户理解和解释模拟结果。 6. **可扩展性**:由于ASE是基于Python的,用户可以利用Python的强大...

    SYBASE ASE 15.0-ASE15.0的新增功能

    - **简介**: ASE 15.0 提供了全面的数据加密功能,可以在数据库级别或列级别实现加密保护,确保敏感信息的安全。 - **应用场景**: 银行、金融等行业中,存储客户个人信息等高敏感度数据时,加密技术是必不可少的...

    ASE15中文学习资料

    1. **实用程序指南**:这部分内容详细介绍了ASE15中的各种管理和维护工具,如SQL Server Management Studio (SSMS) 的对应功能,可能包括数据库备份、恢复、性能监控、查询优化等实用工具的使用方法。通过这本指南,...

    3DsMax中Ase文件的读取

    在3DsMax中,ASE(ASCII Scene Export)文件是一种用于交换3D模型数据的文本格式。这种文件格式是由Autodesk开发的,目的是为了让用户能在不同的3D软件之间方便地导入和导出场景数据,比如3DsMax、Maya、Softimage等...

    Sybase ASE 15.7 开发文档:Web 服务用户指南

    Sybase ASE 15.7 开发文档:Web 服务用户指南 第 1 部分 简介 第 1 章 了解 Adaptive Server Enterprise Web 服务 .......... 3 概述 .......... 3 Adaptive Server Enterprise Web 服务 .......... 4 ASE Web 服务...

    Sybase ASE 15.7 开发文档:系统管理指南(卷一)

    Sybase ASE 15.7 开发文档:系统管理指南(卷一)共两卷 第 1 章系统管理概述 .......... 1 Adaptive Server 管理任务 .......... 1 系统管理任务所需的角色 .......... 2 使用 isql 执行系统管理任务 .......... 4 ...

    ASE.zip_ASE_ASE matlab_Area spectral_matlab ASE_zip

    6. **数据处理与可视化**:MATLAB强大的数据分析和可视化功能可以帮助我们理解ASE与不同参数之间的关系,通过绘制图表来直观展示结果。 在"ASE.zip"压缩包中,包含了可能的MATLAB源代码或脚本,用于模拟和计算ASE。...

    ASE加密码方式_ASE_

    在ASE中,TDE通常通过使用证书或密钥对来实现,确保只有拥有正确密钥的用户才能解密并访问数据。 2. **ASE的表和列加密**:ASE还支持对表中的特定列进行加密,以满足更细粒度的安全需求。这种加密方式允许敏感数据...

    Unity ASE插件(Amplify Shader Editor 1.8.9.035.unitypackage最新版)

    Unity ASE插件,全称Amplify Shader Editor,是一款强大的...通过下载并导入"Amplify Shader Editor 1.8.9.035.unitypackage"文件,你将能够将这些功能集成到你的Unity项目中,从而实现更为精细和生动的游戏视觉体验。

    Sybase ASE 15.0简体中文技术参考手册

    ASE中的JAVA.pdf HA_故障切换.pdf Historical Server.pdf Job Scheduler.pdf Monitor Client.pdf Monitor Server.pdf T-SQL用户指南.pdf WEB服务.pdf XML服务.pdf 全文本搜索引擎.pdf 分布式事务管理.pdf 参考手册-...

    ASE双语加解密工具类(java,net)

    ASE(Advanced Security Engine)是一种强大的数据加密算法,广泛应用于各种软件和系统中,尤其是需要跨平台数据安全交互的场景。本篇文章将详细讲解如何在Java和.NET平台上利用ASE加密机制实现双语加解密,并介绍...

    SYBASE ASE 15.0-ASE中的 Java

    jConnect for JDBC支持高级功能,如事务管理、结果集处理、批量更新等,极大地简化了数据库操作的复杂度。 ##### 3. Java集成工具 ASE 15.0还提供了一系列工具,帮助Java开发者更高效地与数据库交互。这些工具包括...

    SYBASE ASE 15.5 ESD#1 官方教程

    - ASEReplicator 能够将主数据库的数据变化自动同步到一个或多个副本数据库中,从而实现数据分布和高可用性。 2. **与ReplicationServer的口令兼容性**: - ASE 15.5 ESD#1 改进了与ReplicationServer的口令兼容...

    SybaseASE的字符集[参考].pdf

    - 字符集转换失败通常由于不兼容的字符集设置导致,解决方法包括检查和调整服务器、客户端的字符集配置,或在传输数据时进行正确的转换。 掌握这些概念和技术对于在Sybase ASE环境下进行软件开发至关重要,特别是...

    Sybase ASE的字符集知识集锦

    Sybase Adaptive Server Enterprise(ASE)是一款强大的关系型数据库管理系统,其中字符集的配置和管理对于数据的正确存储和处理至关重要。本文将深入探讨字符集、排序顺序以及字符集转换这三个核心概念。 1. **...

    Sybase ASE 15.7 开发文档:系统管理指南(卷二)

    限制结果集的大小 .......... 13 设置 tempdb 空间使用限制 .......... 14 限制空闲时间 .......... 14 创建资源限制 .......... 14 资源限制示例 .......... 15 获得关于现有限制的信息 .......... 16 列出所有现有...

Global site tag (gtag.js) - Google Analytics