问题描述
通过获取n行然后进行具有偏移量的后续调用来进行非常简单的分页的初始尝试会在Oracle中产生重叠的条目。
我期望以下内容能给我带来两组独特的结果。如果将第一行设置为200,则返回的结果是1-100,然后是101-200。
select * from "APPR" /*+ index(APPR APPR_IDX01) */ where ("APPROVER" = 'A') or ("APPROVER" > 'A') order by "APPROVER" fetch first 100 rows only ;
select * from "APPR" /*+ index(APPR APPR_IDX01) */ where ("APPROVER" = 'A') or ("APPROVER" > 'A') order by "APPROVER" offset 100 rows fetch next 100 rows only ;
因此,如果批准人A有150个项目,则第一个结果应为:
- A,项目1
- ....
- A,项目100
后续调用(偏移100)给予
- A,项目101
- ...
- A,项目150
- B,项目1
- B,第2项
- ....
- B,项目201
不幸的是,第二组包含第一批值中的某些条目。可能是一个非常愚蠢的错误,但是我找不到关于为什么应该发生这种情况的解释。
----由于评论而更新 主键由批准者和其他几个字段组成,共同构成一个复合的唯一主键。
该代码将通过ODBC调用,并将在Oracle和MysqL后端上使用。
解决方法
在Oracle中,如果对包含相同值(例如,具有-'A','A','A'...)的列进行“排序依据”,则'A'值内的记录顺序将为
请尝试将查询更改为... order by "APPROVER",rowid
...
大概APPROVER
不是唯一列。由于可能存在重复项,因此order by
子句不稳定,并且offset子句可能会产生重复项。
一个简单的解决方案是在order by
中添加更多列以打破束缚。假设(approver,item)
是一组唯一的列,则为:
select *
from appr
where approver = 'A' or approver > 'A'
order by approver,item
fetch first 100 rows only
-- then: offset 100 rows fetch next 100 rows only
注意:
-
无需在全大写的标识符(表或列名)两边加上双引号:这已经是Oracle中的默认值
在这种简单情况下,{li> -
如果
approver
始终是一个字符,则where
子句可以简化为where approver >= 'A'
-
仅当您真的知道为什么这么做时才使用索引提示(我不是说您不这样做,而是为了以防万一,我删除了它);大多数时候,数据库更了解
or
条件周围的括号是多余的