​ 今天碰到一个分页BUG,记录一下

Oracle之ROWNUM分页

使用ROWNUM进行分页查询

rownum关键字:

​ oracle对外提供的自动给查询结果编号的关键字,与每行的数据没有关系。

注意:

​ rownum关键字只能做< <=的判断,不能进行> >=的判断

SQL1:

1
2
3
4
5
6
7
8
9
select *
FROM (select tmp_tb.*,ROWNUM row_id
FROM (select ID, TO_CHAR(RDRQ ,'YYYY-MM-DD') RDRQ
FROM RED_LIST
WHERE 1=1
ORDER BY RDRQ DESC NULLS LAst
) tmp_tb
WHERE ROWNUM<=30)
WHERE row_id>0;

SQL2:

1
2
3
4
5
6
7
8
9
select *
FROM (select tmp_tb.*,ROWNUM row_id
FROM (select ID, TO_CHAR(RDRQ ,'YYYY-MM-DD') RDRQ
FROM RED_LIST
WHERE 1=1
ORDER BY RDRQ DESC NULLS LAst
) tmp_tb
WHERE ROWNUM<=10)
WHERE row_id>0;

比较两条SQL的执行结果:

​ A4F1BD9FDF580D66E050020A0B033FAF

oracle_address

​ A4F1BD9FDF010D66E050020A0B033FAF

oracle_address

原因:

​ 使用ORDER BY 的时候,排序结果不唯一,导致最终的数据排序不稳定,我们分页截取的部分数据会重复显示。

​ 即当RDRQ相同的值具有几百条时,这时,我们查出来的数据是随机的,不是固定顺序的,此时我们取出来的分页数据是不固定的。

解决方法:

​ 可以在ORDER BY 最后增加PK列或ROWID;即使有重复值,也可以根据索引进行区分。

解决方法如下(两个条件必须同时满足):
  1.sql语句中需要有排序条件。
  2.排序条件如果没有唯一性,那么必须在后边跟上一个唯一性的条件,比如主键。

改进后SQL:

​ 注意:ORDER BY RDRQ DESC,ROWID NULLS LAst

​ NULLS LAst 表示RDRQ 为空值的时候排在最后面

1
2
3
4
5
6
7
8
9
select *
FROM (select tmp_tb.*,ROWNUM row_id
FROM (select ID, TO_CHAR(RDRQ ,'YYYY-MM-DD') RDRQ
FROM RED_LIST
WHERE 1=1
ORDER BY RDRQ DESC NULLS LAst,ROWID
) tmp_tb
WHERE ROWNUM<=30)
WHERE row_id>0;

NULLS LAst 表示空值排在最后面

NULLS first 表示空值排在最前面

最后更新: 2020年06月24日 09:17

原始链接: http://ligangit.com/2020/06/23/Oracle之ROWNUM分页/

× 请我吃糖~
打赏二维码