fetch first 必须搭配 order by 使用,否则报错,因标准要求结果可预测;常见错误是省略 order by,正确写法需显式排序;即使有主键也不能跳过;兜底写法 order by (select null) 在部分数据库支持。

FETCH FIRST 必须搭配 ORDER BY 才能用
不加 ORDER BY 直接写 FETCH FIRST 10 ROWS ONLY,几乎所有支持该语法的数据库(PostgreSQL、SQL Server、Oracle 12c+、SQLite 3.25+)都会报错,错误信息类似 ERROR: FETCH clause cannot be used without ORDER BY。这是因为标准强制要求结果可预测——没排序时“前10条”是随机的,语义不成立。
常见错误写法:
SELECT * FROM users FETCH FIRST 10 ROWS ONLY; -- ❌ 报错
正确写法:
SELECT * FROM users ORDER BY id DESC FETCH FIRST 10 ROWS ONLY; -- ✅
-
ORDER BY可以是单列或多列,升序降序均可 - 即使表有主键或唯一索引,也不能跳过
ORDER BY - 如果业务真不需要排序,就用
ORDER BY (SELECT NULL)这种兜底写法(PostgreSQL/SQL Server 支持,Oracle 不支持)
FETCH FIRST 和 LIMIT 的兼容性差异
你不能靠写一次 FETCH FIRST 就跑通所有数据库。MySQL 在 8.0.22 才开始支持(2026年7月仍属较新特性),而老版本 MySQL、MariaDB、旧版 SQL Server(
典型不兼容场景:
- 在 MySQL 5.7 或 8.0.21 及更早版本中执行
FETCH FIRST 10 ROWS ONLY→ 报错ERROR 1064 (42000): You have an error in your SQL syntax - SQLite 3.24 及更早版本不支持
FETCH,必须用LIMIT 10 - Oracle 11g 及更早版本只认
ROWNUM,FETCH会提示ORA-00933: SQL command not properly ended
跨库项目若需统一写法,要么做方言适配层,要么退回到最保守的 LIMIT / TOP / ROWNUM 分支逻辑。
OFFSET + FETCH 实现分页时容易漏掉的细节
用 OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY 做分页看似简单,但实际部署常踩三个坑:
-
OFFSET值过大(比如 >10000)会导致性能断崖式下降,尤其在没合适索引的排序字段上——数据库得先扫完前 N 行再取后续数据 - 并发写入下,两次分页查询之间若有新记录插入到排序位置中间,会导致某条记录被跳过或重复出现(“幻读”现象)
-
FETCH NEXT 10 ROWS WITH TIES要求排序字段存在重复值才有意义;如果ORDER BY created_at里时间精度到秒,且多行同秒,才可能触发WITH TIES多返回几行;否则它和ONLY效果一样
替代方案建议:对高偏移量分页,优先考虑游标分页(WHERE created_at ),而不是依赖 <code>OFFSET。
Oracle 中 ROWNUM 和 FETCH FIRST 的性能与语义区别
Oracle 用户常纠结该用 ROWNUM 还是 FETCH FIRST。关键不是“哪个更新”,而是“哪个更符合当前需求”:
-
ROWNUM是 Oracle 专属伪列,从结果生成第一行起就编号,所以SELECT * FROM t WHERE rownum 实际是先取任意 10 行再排序——结果不可控;必须套子查询才能正确排序后截断 -
FETCH FIRST是标准语法,语义清晰:先完整排序,再取前 N 行,写法更直觉,也更容易被优化器识别为“top-N query” - 性能上,Oracle 12c+ 对
FETCH FIRST有专门优化,实际执行计划常比等价的ROWNUM子查询更优;但低版本 Oracle(如 11g)只能用ROWNUM
如果你用的是 Oracle 12c 或更高版本,且查询带 ORDER BY,优先写 FETCH FIRST;否则老老实实用 ROWNUM 套子查询结构。











