我用with as 写了一个复杂的sql给开发,后来告诉我分页的时候排序数据有重复,问我是不是with as 不支持分页,这怎么可能,with as跟分页怎么会不兼容呢,它的本质也就是一个select语句啊。
查看查询结果,发现排序字段有很多重复值,导致排序随机,造成分页数据重复问题。跟with as没关系,为with as 平反,哈哈。
下面做一个小demo来重现此问题:
drop table test purge;
Create table test as select * from dba_tables;
–查询第一页:
SCOTT@PROD> select * from (select temp.*,rownum rn from (select table_name, owner from test order by owner) temp where rownum <= 1* 10) temp1 where rn>(1-1)*10;
复制
TABLE_NAME OWNER RN ------------------------------ -------------------- ---------- WLM_METRICS_STREAM APPQOSSYS 1 WLM_FEATURE_USAGE APPQOSSYS 2 WLM_VIOLATION_STREAM APPQOSSYS 3 WLM_MPA_STREAM APPQOSSYS 4 WLM_CLASSIFIER_PLAN APPQOSSYS 5 AUD$UNIFIED AUDSYS 6 DR$CLASS CTXSYS 7 DR$OBJECT_ATTRIBUTE_LOV CTXSYS 8 DR$OBJECT_ATTRIBUTE CTXSYS 9 DR$OBJECT CTXSYS 10 10 rows selected.
复制
–查询第二页
SCOTT@PROD> select * from (select temp.*,rownum rn from (select table_name, owner from test order by owner) temp where rownum <= 2* 10) temp1 where rn>(2-1)*10;
复制
TABLE_NAME OWNER RN ------------------------------ -------------------- ---------- SYS_IOT_OVER_61247 CTXSYS 11 DR$POLICY_TAB CTXSYS 12 DR$INDEX_VALUE CTXSYS 13 DR$INDEX_PARTITION CTXSYS 14 DR$INDEX CTXSYS 15 DR$PREFERENCE_VALUE CTXSYS 16 DR$PREFERENCE CTXSYS 17 DR$OBJECT_ATTRIBUTE_LOV CTXSYS 18 DR$OBJECT_ATTRIBUTE CTXSYS 19 DR$OBJECT CTXSYS 20 10 rows selected.
复制
–查询第三页
SCOTT@PROD> select * from (select temp.*,rownum rn from (select table_name, owner from test order by owner) temp where rownum <= 3* 10) temp1 where rn>(3-1)*10;
复制
TABLE_NAME OWNER RN ------------------------------ -------------------- ---------- SYS_IOT_OVER_61247 CTXSYS 21 DR$POLICY_TAB CTXSYS 22 DR$INDEX_VALUE CTXSYS 23 DR$INDEX_PARTITION CTXSYS 24 DR$INDEX CTXSYS 25 DR$PREFERENCE_VALUE CTXSYS 26 DR$PREFERENCE CTXSYS 27 DR$OBJECT_ATTRIBUTE_LOV CTXSYS 28 DR$OBJECT_ATTRIBUTE CTXSYS 29 DR$OBJECT CTXSYS 30 10 rows selected.
复制
我们发现第二页与第三页数据相同,接下来再查第四页、第五页数据也相同,直到查第六页时发生变化
–查询第六页
SCOTT@PROD> select * from (select temp.*,rownum rn from (select table_name, owner from test order by owner) temp where rownum <= 6* 10) temp1 where rn>(6-1)*10; 2 3 4 5 6 7 TABLE_NAME OWNER RN ------------------------------ -------------------- ---------- DR$POLICY_TAB CTXSYS 51 DR$INDEX_VALUE CTXSYS 52 DR$INDEX_PARTITION CTXSYS 53 DR$INDEX CTXSYS 54 DR$PREFERENCE_VALUE CTXSYS 55 DR$PREFERENCE CTXSYS 56 DR$OBJECT_ATTRIBUTE_LOV CTXSYS 57 DR$OBJECT_ATTRIBUTE CTXSYS 58 DR$OBJECT CTXSYS 59 EXADIRECT_ACL DBSFWUSER 60
复制
第六页为什么会变呢,因为排序字段的值发生了变化。
总结:分页,没有排序字段不行,因为查询每页的结果时,每页的查询sql相对独立,不能保证oracle每次查询结果相同;有了排序字段,但是排序字段重复数据太多,极端情况完全相同,也是近似无序,同样也会出现翻页时有重复数据。
解决办法:排序字段上加上唯一值字段,或者排序组合字段无重复值,就不会出现重复数据了。
例如,我们在上面排序字段上加入table_name,翻页就不会出现重复数据了。
–第一页
SCOTT@PROD> select * from (select temp.*,rownum rn from (select table_name, owner from test order by owner,table_name) temp where rownum <= 1* 10) temp1 where rn>(1-1)*10; 2 3 4 5 6 7 TABLE_NAME OWNER RN ------------------------------ -------------------- ---------- WLM_CLASSIFIER_PLAN APPQOSSYS 1 WLM_FEATURE_USAGE APPQOSSYS 2 WLM_METRICS_STREAM APPQOSSYS 3 WLM_MPA_STREAM APPQOSSYS 4 WLM_VIOLATION_STREAM APPQOSSYS 5 AUD$UNIFIED AUDSYS 6 DR$ACTIVELOGS CTXSYS 7 DR$AUTOOPT CTXSYS 8 DR$CLASS CTXSYS 9 DR$DBO CTXSYS 10 10 rows selected. --第二页 SCOTT@PROD> select * from (select temp.*,rownum rn from (select table_name, owner from test order by owner,table_name) temp where rownum <= 2* 10) temp1 where rn>(2-1)*10; 2 3 4 5 6 7 TABLE_NAME OWNER RN ------------------------------ -------------------- ---------- DR$DELETE CTXSYS 11 DR$DICTIONARY CTXSYS 12 DR$FEATURE_USED CTXSYS 13 DR$FREQTOKS CTXSYS 14 DR$IDX_DICTIONARIES CTXSYS 15 DR$INDEX CTXSYS 16 DR$INDEX_CDI_COLUMN CTXSYS 17 DR$INDEX_ERROR CTXSYS 18 DR$INDEX_OBJECT CTXSYS 19 DR$INDEX_PARTITION CTXSYS 20 10 rows selected. --第三页 SCOTT@PROD> select * from (select temp.*,rownum rn from (select table_name, owner from test order by owner,table_name) temp where rownum <= 3* 10) temp1 where rn>(3-1)*10; 2 3 4 5 6 7 TABLE_NAME OWNER RN ------------------------------ -------------------- ---------- DR$INDEX_SET CTXSYS 21 DR$INDEX_SET_INDEX CTXSYS 22 DR$INDEX_VALUE CTXSYS 23 DR$NUMBER_SEQUENCE CTXSYS 24 DR$NVTAB CTXSYS 25 DR$OBJECT CTXSYS 26 DR$OBJECT_ATTRIBUTE CTXSYS 27 DR$OBJECT_ATTRIBUTE_LOV CTXSYS 28 DR$ONLINE_PENDING CTXSYS 29 DR$PARALLEL CTXSYS 30 10 rows selected.
复制
补充:
其实最好是加上rowid,因为索引本身是存储rowid信息的,而且对于相同索引值的行是按rowid来排序的,也就是说排序列上加上rowid即可以避免重复,又可以不用在索引中加入其他字段而增大索引的体积。
最后修改时间:2021-11-14 20:51:43
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
Oracle RAC 一键安装翻车?手把手教你如何排错!
Lucifer三思而后行
548次阅读
2025-04-15 17:24:06
【纯干货】Oracle 19C RU 19.27 发布,如何快速升级和安装?
Lucifer三思而后行
467次阅读
2025-04-18 14:18:38
Oracle SQL 执行计划分析与优化指南
Digital Observer
446次阅读
2025-04-01 11:08:44
XTTS跨版本迁移升级方案(11g to 19c RAC for Linux)
zwtian
445次阅读
2025-04-08 09:12:48
墨天轮个人数说知识点合集
JiekeXu
442次阅读
2025-04-01 15:56:03
【ORACLE】记录一些ORACLE的merge into语句的BUG
DarkAthena
438次阅读
2025-04-22 00:20:37
【ORACLE】你以为的真的是你以为的么?--ORA-38104: Columns referenced in the ON Clause cannot be updated
DarkAthena
413次阅读
2025-04-22 00:13:51
Oracle数据库一键巡检并生成HTML结果,免费脚本速来下载!
陈举超
411次阅读
2025-04-20 10:07:02
Oracle 19c RAC更换IP实战,运维必看!
szrsu
393次阅读
2025-04-08 23:57:08
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
357次阅读
2025-04-17 17:02:24