核心结论:Oracle 分页主要有两种主流写法,第一种是 Oracle 12c 及以上版本推荐的OFFSET FETCH 分页语法,写法简洁;第二种是老版本 Oracle(11g 及更早)通用的ROWNUM 双层子查询分页,也是面试高频考点,分页最重要前提一定要加 ORDER BY 排序,不然分页数据会乱序重复。
一、Oracle12c+ OFFSET FETCH 标准分页(推荐)
语法格式
SELECT
FROM 表名
ORDER BY 排序字段
OFFSET 起始行号 ROWS
FETCH NEXT 每页条数 ROWS ONLY;
举例:查询第 2 页,每页 10 条,按 id 升序
SELECT
FROM T_USER
ORDER BY ID
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
说明:OFFSET 10 代表跳过前 10 行,也就是从第 11 行开始,取出接下来 10 行,就是第二页数据。
二、Oracle11g ROWNUM 双层嵌套分页(老版本必用)
原理:ROWNUM 是伪列,查询的时候动态生成,不能直接写大于某个数字,所以必须套两层子查询,第一层先排序生成伪列,第二层再做范围筛选。
通用模板
SELECT
FROM (
SELECT T., ROWNUM AS RN
FROM (
SELECT FROM 表名 ORDER BY 排序字段
) T
WHERE ROWNUM <= 结束行号
)
WHERE RN > 起始行号;
举例:第 2 页,每页 10 条,也就是 11~20 行
SELECT
FROM (
SELECT T., ROWNUM AS RN
FROM (
SELECT FROM T_USER ORDER BY ID
) T
WHERE ROWNUM <= 20
)
WHERE RN > 10;
计算公式:
每页 pageSize,当前页码 pageNum
起始行 = (pageNum - 1) pageSize
结束行 = pageNum pageSize
三、两种分页写法对比
| 分页方式 | 支持版本 | 优点 | 缺点 |
|---|---|---|---|
| OFFSET FETCH | Oracle12c 及更高版本 | 语法简洁易读 | 11g 不支持 |
| ROWNUM 双层查询 | 全部 Oracle 版本 | 兼容性最好 | SQL 嵌套多,写法繁琐 |
四、重要注意点
1 必须 ORDER BY 排序,如果没有排序,ROWNUM 分页结果不稳定,翻页会出现重复或者丢数据
2 ROWNUM 是在排序之前生成,所以不能把排序写在外层,这是最常见报错踩坑点
3 如果带查询条件,WHERE 条件写在内层原始查询里面,例如
SELECT
FROM (
SELECT T., ROWNUM AS RN
FROM (
SELECT FROM T_USER WHERE STATUS = 1 ORDER BY ID
) T
WHERE ROWNUM <= 20
)
WHERE RN > 10;
【常见问题】
问题 1 oracle 查询分页 sql 语句,为什么直接写 ROWNUM>10 查不到数据
回答:oracle 查询分页 sql 语句里面,ROWNUM 是查询过程逐行分配,第一行就不满足 > 10,后面行永远不会生成 ROWNUM,所以必须双层嵌套,先把 ROWNUM 固化成真实列 RN,再筛选 RN>10。
问题 2 oracle 查询分页 sql 语句,11g 能不能使用 OFFSET FETCH
回答:oracle 查询分页 sql 语句,OFFSET FETCH 是 12c 新增语法,Oracle11g 不支持,只能使用 ROWNUM 双层子查询分页。
问题 3 oracle 查询分页 sql 语句,分页查询很慢怎么优化
回答:oracle 查询分页 sql 语句慢,优先给 ORDER BY 排序字段建立索引,避免全表扫描,大表尽量不要 SELECT ,只查询需要的字段,减少 IO 开销。
【免责申明】
本内容为 Oracle SQL 通用语法讲解,不同 Oracle 小版本执行细节略有差异,生产环境大表分页建议结合执行计划做性能调优,本内容不替代生产环境专业 DBA 方案。


