oracle使用order by排序后,点击下一页数据无变化解决办法

本文摘自百度经验;

Oracle分页采用三层嵌套+rownum分页时,如果有order by,就会有一个小坑,一不留神就掉进去了。

前置条件:分页脚本中存在order by

问题暴露:分页时好时坏

问题本质:order by 在相同的数据下,排序具有不确定性

解决方法:最简单的办法,习惯性在order by后面加rownum或rowid,推荐加rowid

补充:如果有分析函数的情况按照具体情况处理,不可千篇一律


  1. 1
    我的分页sql如下所示:

    select *
      from (select tmp.*, rownum num
              from (SELECT B.ID,
                           B.BAR_CODE,
                           B.check_date 
                      FROM table B                 
                     WHERE 1 = 1 ...
                     order by B.check_date desc) tmp
             where rownum <= n1)
     where num > n2;

    在查询过程中n1,n2,配置110、120,130、140,150时,查询出的数据重复排序规则,也就是说不能保证每次分页查询时的记录的rownum一致。因此得到的数据也不是我们预想的,经测试的确如此。

  2. oracle使用order by排序后,点击下一页数据无变化解决办法     oracle使用order by排序后,点击下一页数据无变化解决办法

  3. 经过分析发现,根据CHECK_DATE排序后,当CHECK_DATE相同的数据有很多个时,并没有给它一个排序规则,也就是说不能保证每次分页查询时的记录的rownum一致。因此得到的数据也不是我们预想的,经测试的确如此。


    因此,对于此问题的解决方法如下:
    第一种:修改select 语句后的order by 字段,使排序规则有效,比如,首先按机构、然后按主键或者不加排序子句,或者干脆按rowid排序都是可以的,不过后者也就没有什么业务含义了。

  4. Tips:如果产品还未上线,可以修改代码,建议使用第一种,如果是生产环境,不便修改代码的话,可以使用第二种方法

    第二种方法:修改排序字段的数据内容。
    由于排序字段数据重复,导致排序结果无规则,而抱着先解决问题的态度,我就先修改数据内容,使期排序有效。这里也是有技巧的,比如怎么修改CHECK_DATE字段值保证排序有效,而又不用使时间字段变化太多呢?
    我的做法是,CHECK_DATE=CHECK_DATE+rownum/24/60/60,也就是按行号增加1秒。
    sql如下:
    update ... a
        set a.CHECK_DATE=(select b.CHECK_DATE+rn/24/60/60
                         from(select a.rowid rid,rownum rn,a.* from ... a) b
                     where a.rowid=b.rid )
    oracle 数据库分页中的order by 后数据重复问题


    经过修改后,分页查询数据显示正常,不再出现重复值了。

    注意事项

    • 看来以后使用分页sql时,增加排序时一定要注意一下了。