日期:2014-05-16  浏览次数:20513 次

oracle分页所遇到的rownum问题:要增加order by的唯一性

昨天做完项目后让测试测试了一把,测试说分页查询貌似不起作用,翻到第4页以后,看到的数据结果都是相同的。

当时我就觉得很纳闷,不可能啊,分页组件应该是好的,咋可能有问题呢。带着疑问,我打开了自己的ide,在自己的机器上跑了一把,果然有问题。

有问题就要找问题:

首先把2条查询结果相同的sql打印出来到数据库中执行:

?

sql1:
select *
  from (select t.*, rownum rn
          from (select t_e_id, t_e_name, t_e_tel, t_e_areacode
                  from (select t.eid t_e_id,
                               t.ename t_e_name,
                               t.etel t_e_tel,
                               t.areaid t_e_areacode,
                               t.biz_delete_time,
                               decode(areaid, '0730', '0', '1') orderseq
                          from vr_enterprise t
                         where t.eid not in (select eid from t_biz_erelation))
                 order by orderseq, biz_delete_time nulls last) t
         where rownum < 25)
 where rn >= 19
 
sql2:
select *
  from (select t.*, rownum rn
          from (select t_e_id, t_e_name, t_e_tel, t_e_areacode
                  from (select t.eid t_e_id,
                               t.ename t_e_name,
                               t.etel t_e_tel,
                               t.areaid t_e_areacode,
                               t.biz_delete_time,
                               decode(areaid, '0730', '0', '1') orderseq
                          from vr_enterprise t
                         where t.eid not in (select eid from t_biz_erelation))
                 order by orderseq, biz_delete_time nulls last) t
         where rownum < 18)
 where rn >= 12

?

结果显示大多数行是相同的。

为了找到问题所在,只有先一步一步的精简化sql,看在哪一步出的问题。

于是找到了,问题出现在where rownum<18的时候数据改变了,为什么加了个where条件结果就会变呢?

表示想不通啊。。。。。

没办法,只好baidu了,baidu了半天,都没人给个解释啊。。。。。

后来同事说,换个写法试试,于是改了另一种写法,如下:

select *
  from (select t.*, rownum rn
          from (select t_e_id, t_e_name, t_e_tel, t_e_areacode
                  from (select t.eid t_e_id,
                               t.ename t_e_name,
                               t.etel t_e_tel,
                               t.areaid t_e_areacode,
                               t.biz_delete_time,
                               decode(areaid, '0730', '0', '1') orderseq
                          from vr_enterprise t
                         where t.eid not in (select eid from t_biz_erelation))
                 order by orderseq, biz_delete_time nulls last) t) m
 where m.rn >= 1
   and m.rn < 25

?

这个方法果然凑效,凑效是凑效,关键是为什么前面那种方法不行呢?抓问题要刨根问底。

看来baidu不行,得换google搜索了。找呀找找呀找,在oracle的ask tom上,tom详细的介绍了rownum的用法,在这里http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html

One important thing about using this