Oracle 12c+应优先用OFFSET/FETCH FIRST分页,因其严格按ORDER BY→OFFSET→FETCH执行、语义清晰;而ROWNUM需两层子查询且在排序前赋值,WHERE ROWNUM BETWEEN无效。

MySQL 和 PostgreSQL 用 LIMIT,SQL Server 用 TOP,Oracle 12c+ 用 FETCH FIRST —— 没有统一写法,必须按数据库类型选。
MySQL / PostgreSQL 怎么写 LIMIT?
最常见也最直观:LIMIT 放在语句末尾,支持单参数(取前N条)或双参数(跳过M条后取N条)。
-
SELECT * FROM users LIMIT 5;→ 取前5条 -
SELECT * FROM users LIMIT 10 OFFSET 20;→ 跳过前20条,取接下来10条(PostgreSQL 写法;MySQL 也支持,但20, 10更常用) - 注意:
LIMIT必须配合ORDER BY使用才有确定性结果;不加排序时,每次执行可能返回不同记录 - 性能上,
LIMIT 1配合索引字段的WHERE条件,能快速终止扫描,比全表查再截断快得多
SQL Server 为什么不能用 LIMIT?
SQL Server 不识别 LIMIT,会直接报错 Incorrect syntax near 'LIMIT'。必须用 TOP 关键字,且位置固定在 SELECT 后。
-
SELECT TOP 5 * FROM users;→ 正确 -
SELECT * FROM users TOP 5;→ 语法错误 - 如果要等价于
LIMIT 10 OFFSET 20,得用OFFSET-FETCH(SQL Server 2012+):SELECT * FROM users ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY; -
TOP默认不保证顺序,同样建议搭配ORDER BY,否则结果不可预测
Oracle 12c 以后怎么写分页和取前N条?
Oracle 旧版本靠 ROWNUM 嵌套子查询,写法绕;12c 引入标准 SQL 的 FETCH FIRST,更清晰。
-
SELECT * FROM users FETCH FIRST 5 ROWS ONLY;→ 取前5条 -
SELECT * FROM users ORDER BY created_at OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;→ 等价于分页第3页(每页10条) - 注意:
FETCH必须跟在ORDER BY后,否则报错ORA-00933: SQL command not properly ended - 如果用老版本 Oracle(11g 或更早),只能用
ROWNUM:先ORDER BY子查询,外层再限制ROWNUM ,否则 <code>ROWNUM在排序前就已分配,结果不对
跨数据库写法兼容性差在哪?
核心差异不在“取前N条”这个动作本身,而在于语法位置、是否强制要求排序、以及偏移逻辑的表达方式。
-
LIMIT是 MySQL/PG 的“后置修饰”,TOP是 SQL Server 的“前置修饰”,FETCH是 Oracle 的“末尾子句”——没法写一次跑所有库 - 不加
ORDER BY时,各数据库都可能返回任意顺序的N条,但开发常误以为“自然插入顺序”就是稳定顺序,实际不是 - ORM 框架(如 SQLAlchemy、MyBatis)会自动适配,但手写原生 SQL 时,切勿复制粘贴就上线,尤其从测试环境(可能是 PG)抄到生产(是 SQL Server)

















