Pagination
Clauses that cap the number of rows returned and skip past an offset — LIMIT / OFFSET, FETCH FIRST, TOP.
LIMIT OFFSET FETCH FIRST TOP row limiting LIMIT/OFFSET
pagination limit offset row limiting TOP FETCH FIRST
| Database | Status | Syntax Family | Min Version |
|---|---|---|---|
| PostgreSQL | full | limit-offset | - |
| MySQL | full | limit-offset | - |
| MariaDB | full | limit-offset | - |
| Oracle | full | fetch-first | 12c |
| SQL Server | full | top-offset-fetch | 2012 |
| SQLite | full | limit-offset | - |
| Redshift | full | limit-offset | - |
| DB2 | full | fetch-first | - |
| Snowflake | full | limit-offset | - |
| BigQuery | full | limit-offset | - |
Compare Databases
Database Details
PostgreSQL
full
-- LIMIT/OFFSET syntax
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;
-- SQL-standard syntax (PostgreSQL 8.4+)
SELECT * FROM products
ORDER BY created_at DESC
OFFSET 40 ROWS
FETCH FIRST 20 ROWS ONLY;- Accepts both LIMIT / OFFSET and the SQL-standard OFFSET / FETCH FIRST (since 8.4).
- LIMIT ALL is a no-op, equivalent to omitting LIMIT entirely.
Docs: LIMIT and OFFSET
MySQL
full
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;
-- Alternative syntax
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 40, 20;- The alternate LIMIT offset, count comma form reverses the argument order relative to LIMIT ... OFFSET; easy source of off-by-one bugs.
- No FETCH FIRST. To skip without a limit, pass the documented LIMIT 18446744073709551615 OFFSET n (max BIGINT).
Docs: SELECT ... LIMIT
MariaDB
full
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;
-- SQL-standard syntax (MariaDB 10.6+)
SELECT * FROM products
ORDER BY created_at DESC
OFFSET 40 ROWS
FETCH FIRST 20 ROWS ONLY;- Same LIMIT / OFFSET and comma syntax as MySQL.
- Adds the SQL-standard OFFSET / FETCH FIRST since 10.6.
Docs: LIMIT
Oracle
full
-- Row limiting clause (Oracle 12c+)
SELECT * FROM products
ORDER BY created_at DESC
OFFSET 40 ROWS
FETCH FIRST 20 ROWS ONLY;
-- Legacy ROWNUM approach (all versions)
SELECT * FROM (
SELECT a.*, ROWNUM rn FROM (
SELECT * FROM products ORDER BY created_at DESC
) a WHERE ROWNUM <= 60
) WHERE rn > 40;- OFFSET / FETCH FIRST added in 12c. Also accepts FETCH FIRST n PERCENT ROWS ONLY and WITH TIES.
- Before 12c, pagination required wrapping the ORDER BY in a ROWNUM subquery.
Docs: Row Limiting Clause
SQL Server
full
-- TOP syntax (simple limiting, all versions)
SELECT TOP 20 * FROM products
ORDER BY created_at DESC;
-- OFFSET/FETCH syntax (SQL Server 2012+)
SELECT * FROM products
ORDER BY created_at DESC
OFFSET 40 ROWS
FETCH NEXT 20 ROWS ONLY;- TOP n limits rows but cannot skip. TOP also accepts WITH TIES and PERCENT.
- OFFSET / FETCH (2012+) requires an ORDER BY and cannot be combined with TOP in the same query.
SQLite
full
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;- Also accepts the MySQL-style comma form LIMIT offset, count.
- LIMIT -1 is a no-op. No FETCH FIRST.
Docs: SELECT - LIMIT clause
Redshift
full
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;- Same LIMIT / OFFSET and FETCH FIRST as PostgreSQL. Use keyset pagination for deep paging; large OFFSET is expensive on columnar storage.
Docs: ORDER BY Clause
DB2
full
SELECT * FROM products
ORDER BY created_at DESC
OFFSET 40 ROWS
FETCH FIRST 20 ROWS ONLY;- FETCH FIRST n ROWS ONLY has been there for a long time; OFFSET joined in 11.1.
- 11.5+ also accepts LIMIT / OFFSET for MySQL-compatibility.
- Before 11.1, skip-based paging required ROW_NUMBER() in a subquery.
Docs: FETCH FIRST Clause
Snowflake
full
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;- Accepts both LIMIT / OFFSET and FETCH FIRST.
Docs: LIMIT / FETCH
BigQuery
full
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;- LIMIT / OFFSET only; no FETCH FIRST.
Docs: LIMIT and OFFSET Clause