在 Oracle 数据库中,实现分页查询有几种常用方法,具体取决于 Oracle 的版本。下面我详细说明几种方法,并给出示例:
1️⃣ Oracle 12c 及以上版本 — 使用 OFFSET … FETCH
Oracle 12c 引入了 OFFSET … FETCH
语法,类似于 MySQL 的 LIMIT
。这是最简单、推荐的方式。
语法示例:
SELECT *
FROM employees
ORDER BY employee_id
OFFSET 10 ROWS -- 跳过前 10 条记录
FETCH NEXT 5 ROWS ONLY; -- 获取接下来的 5 条记录
说明:
OFFSET n ROWS
:跳过前 n 条记录FETCH NEXT m ROWS ONLY
:获取 m 条记录- 必须配合
ORDER BY
,否则分页结果可能不稳定
2️⃣ Oracle 11g 及以前版本 — 使用 ROWNUM
或子查询
在 11g 及以下版本,Oracle 没有 LIMIT
,通常通过子查询和 ROWNUM
实现分页。
语法示例:
SELECT *
FROM (
SELECT e.*, ROWNUM rnum
FROM (
SELECT *
FROM employees
ORDER BY employee_id
) e
WHERE ROWNUM <= 15
)
WHERE rnum > 10;
说明:
- 内层子查询
e
用于排序 - 第二层查询使用
ROWNUM <= 15
限制最大行数 - 外层查询
rnum > 10
实现分页起点
这里相当于获取 第 11~15 条记录。
3️⃣ Oracle 11g 及以前版本 — 使用 ROW_NUMBER()
通过 ROW_NUMBER()
函数按指定排序生成行号,然后再分页。
语法示例:
SELECT *
FROM (
SELECT e.*, ROW_NUMBER() OVER (ORDER BY employee_id) AS rn
FROM employees e
)
WHERE rn BETWEEN 11 AND 15;
说明:
ROW_NUMBER() OVER (ORDER BY ...)
给每行生成行号WHERE rn BETWEEN start AND end
实现分页- 相比
ROWNUM
方法,更灵活,排序不会受 ROWNUM 限制
✅ 总结推荐
Oracle版本 | 方法 | 推荐理由 |
---|---|---|
12c+ | OFFSET … FETCH | 简单明了,语法接近 MySQL |
11g及以下 | ROW_NUMBER() | 灵活、可控、适合复杂分页 |
11g及以下 | ROWNUM + 子查询 | 简单,但排序可能受限制 |
下面我写一个 通用的 Oracle 分页查询模板,直接套用就能分页,无论 11g 还是 12c 都适用。
这个模板使用 ROW_NUMBER()
,在任何版本都可以用,也支持自定义排序和分页参数。
通用分页查询模板(Oracle 11g/12c 都可用)
-- 参数说明:
-- :page_number - 当前页码(从1开始)
-- :page_size - 每页显示的记录数
SELECT *
FROM (
SELECT t.*,
ROW_NUMBER() OVER (ORDER BY t.<排序列>) AS rn
FROM <表名> t
WHERE 1=1
-- 可加其他查询条件,例如:
-- AND t.status = 'ACTIVE'
) sub
WHERE rn BETWEEN (:page_number - 1) * :page_size + 1
AND :page_number * :page_size;
示例:查询员工表第 2 页,每页 5 条记录
SELECT *
FROM (
SELECT e.*,
ROW_NUMBER() OVER (ORDER BY e.employee_id) AS rn
FROM employees e
) sub
WHERE rn BETWEEN (2 - 1) * 5 + 1
AND 2 * 5;
- 计算过程:
- 起始行:
(2-1)*5 + 1 = 6
- 结束行:
2*5 = 10
- 起始行:
- 实际返回 第 6~10 条记录
说明
<排序列>
必须指定,否则分页顺序不稳定。- 可以在
WHERE 1=1
后添加更多筛选条件。 - 如果是 Oracle 12c+,也可以用更简洁的
OFFSET … FETCH
:
SELECT *
FROM employees
ORDER BY employee_id
OFFSET (:page_number-1)*:page_size ROWS
FETCH NEXT :page_size ROWS ONLY;