MySQL LIMIT to SQL Server OFFSET/FETCH Crosswalk

SQL Server 2012+'s OFFSET/FETCH clause covers what MySQL's LIMIT does, but requires an explicit ORDER BY, and older SQL Server versions need a completely different ROW_NUMBER()-based rewrite.

Requires review Works only under specific conditions — read the caveats before relying on it.

MySQL feature
LIMIT ... OFFSET ...
SQL Server equivalent
OFFSET ... ROWS FETCH NEXT ... ROWS ONLY

Main limitation: SQL Server's OFFSET/FETCH clause (2012+) requires an explicit ORDER BY immediately before it — there is no unordered-LIMIT equivalent; MySQL's LIMIT works with or without ORDER BY, though relying on unordered LIMIT results is fragile in MySQL too.

Quick mapping

MySQL LIMIT ... OFFSET ...
SQL Server OFFSET ... ROWS FETCH NEXT ... ROWS ONLY

Examples

Paginating with a fixed page size

MySQL
SELECT * FROM products ORDER BY id LIMIT 10 OFFSET 20;
SQL Server
SELECT * FROM products ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
A direct rewrite for SQL Server 2012+; note the mandatory ORDER BY and the more verbose ROWS/ROWS ONLY keywords.

Older SQL Server (pre-2012) requires a full rewrite

MySQL
SELECT * FROM products ORDER BY id LIMIT 10 OFFSET 20;
SQL Server
WITH numbered AS (
  SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS rn FROM products
)
SELECT * FROM numbered WHERE rn BETWEEN 21 AND 30;
Without OFFSET/FETCH support, pagination must be rebuilt around ROW_NUMBER() — a genuine rewrite, not a drop-in syntax swap.

Caveats

Caveat

SQL Server's OFFSET/FETCH clause (2012+) requires an explicit ORDER BY immediately before it — there is no unordered-LIMIT equivalent; MySQL's LIMIT works with or without ORDER BY, though relying on unordered LIMIT results is fragile in MySQL too.

Caveat

MySQL's shorthand LIMIT offset, count reverses the order of the two numbers compared to the equivalent LIMIT count OFFSET offset form — always use the explicit LIMIT count OFFSET offset spelling when porting, to avoid transposing the values.

Caveat

SQL Server versions before 2012 have no OFFSET/FETCH syntax at all; that older code must be rewritten using ROW_NUMBER() OVER (ORDER BY ...) in a CTE or subquery, filtering on the computed row number — a materially different rewrite, not a syntax substitution.

References

  • MySQL Reference Manual — LIMIT Query Optimization (v8.4) — checked 2026-07-29
  • Microsoft SQL Server docs — OFFSET-FETCH Clause (Transact-SQL) — checked 2026-07-29

Last verified 2026-07-29.