Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

There are a method to paging using ANSI SQL only?

Tags:

sql

ansi-sql

I know:

  • Firebird: FIRST and SKIP;
  • MySQL: LIMIT;
  • SQL Server: ROW_NUMBER();

Does someone knows a SQL ANSI way to perform result paging?

like image 260
Click Ok Avatar asked Jan 21 '09 01:01

Click Ok


2 Answers

Yes (SQL ANSI 2003), feature E121-10, combined with the F861 feature you have :

ORDER BY column OFFSET n1 ROWS FETCH NEXT n2 ROWS ONLY;

Like:

SELECT Name, Address FROM Employees ORDER BY Salary OFFSET 2 ROWS
FETCH NEXT 2 ROWS ONLY;

Examples:

  • postgres: https://dbfiddle.uk/?rdbms=postgres_9.5&fiddle=e25bb5235ccce77c4f950574037ef379
  • oracle: https://dbfiddle.uk/?rdbms=oracle_21&fiddle=07d54808407b9dbd2ad209f2d0fe7ed7
  • sqlserver: https://dbfiddle.uk/?rdbms=sqlserver_2019l&fiddle=e25bb5235ccce77c4f950574037ef379
  • db2: https://dbfiddle.uk/?rdbms=db2_11.1&fiddle=e25bb5235ccce77c4f950574037ef379
  • YugabyteDB: https://dbfiddle.uk/?rdbms=yugabytedb_2.8&fiddle=e25bb5235ccce77c4f950574037ef379

Unfortunately, MySQL does not support this syntax, you need something like:

ORDER BY column LIMIT n1 OFFSET n2
  • But MariaDB does: https://dbfiddle.uk/?rdbms=mariadb_10.6&fiddle=e25bb5235ccce77c4f950574037ef379
like image 167
celsowm Avatar answered Sep 17 '22 01:09

celsowm


No official way, no.*

Generally you'll want to have an abstracted-out function in your database access layer that will cope with it for you; give it a hint that you're on MySQL or PostgreSQL and it can add a 'LIMIT' clause to your query, or rownum over a subquery for Oracle and so on. If it doesn't know it can do any of those, fall back to fetching the lot and returning only a slice of the full list.

*: eta: there is now, in ANSI SQL:2003. But it's not globally supported, it often performs badly, and it's a bit of a pain because you have to move/copy your ORDER into a new place in the statement, which makes it harder to wrap automatically:

SELECT * FROM (
    SELECT thiscol, thatcol, ROW_NUMBER() OVER (ORDER BY mtime DESC, id) AS rownumber
)
WHERE rownumber BETWEEN 10 AND 20 -- care, 1-based index
ORDER BY rownumber;

There is also the "FETCH FIRST n ROWS ONLY" suffix in SQL:2008 (and DB2, where it originated). But like the TOP prefix in SQL Server, and the similar syntax in Informix, you can't specify a start point, so you still have to fetch and throw away some rows.

like image 29
bobince Avatar answered Sep 19 '22 01:09

bobince