项目数据库 MySQL → Oracle,记录一下 Oracle 的分页实现

ROWNUM

与 MySQL 不同,Oracle 中没有 LIMIT 关键字,分页的实现是利用 ROWNUM

ROWNUM 是 Oracle 给查询返回的行添加的顺序编号,从 1 开始向后递增,用于显示行号, ROWNUM 不能以任何表的名称作为前缀

基本用法

SELECT T.* FROM USER T
NAME AGE
张三 19
李四 22
王五 20
SELECT T.*, ROWNUM FROM USER T
NAME AGE ROWNUM
张三 19 1
李四 22 2
王五 20 3

过滤行号

ROWNUM 对于< N(正整数)的条件认为是成立的

SELECT T.*, ROWNUM FROM USER T WHERE ROWNUM < 3
NAME AGE ROWNUM
张三 19 1
李四 22 2

但当条件为 ROWNUM > N(正整数)时是查不出来记录的,因为 ROWNUM 是一个从 1 开始的伪列,当第一条不满足的话,第二条的 ROWNUM 又成了 1,以此类推,永远不会有满足条件的记录

SELECT T.*, ROWNUM FROM USER WHERE ROWNUM > 2
NAME AGE ROWNUM
     

搭配 ORDER BY

如果把刚刚的查询按照 AGE 进行排序,ROWNUM 会出现乱序的情况

SELECT T.*, ROWNUM FROM USER T ORDER BY AGE
NAME AGE(无索引) ROWNUM
张三 19 1
王五 20 3
李四 22 2

在 SELECT 语句中有 ORDER BY,ORDER BY 一般都在最后一步执行。但如果 ORDER BY 子句里的字段被设置了主键约束或是被设置索引,那么 ORDER BY 执行之后,会重新对结果集的 ROWNUM 值进行编号

NAME AGE(有索引) ROWNUM
张三 19 1
王五 20 2
李四 22 3

分页实现

通常情况下 ORDER BY 的字段不一定都带有索引,所以要实现分页的话需要进行嵌套

SELECT * FROM 
 ( SELECT T1.*, ROWNUM RN FROM 
   	( SELECT * FROM USER ORDER BY AGE ) T1
 ) T2 
WHERE T2.RN > start AND T2.RN <= end

注意

ROWNUM 在使用时表名必须带别名