Насколько универсальна инструкция LIMIT в SQL?

Я собираюсь обобщить приложение репликации Django DB, и он использует инструкцию:

SELECT %s FROM %s LIMIT 1 

для извлечения 1 строки и использования PAPI DBAPI для описания полей, он отлично работает с ORACLE и MySQL, но как кросс-платформа является оператором LIMIT?

http://en.wikipedia.org/wiki/Select_(SQL)#Result_limits перечисляет все основные варианты команды select.

Я считаю, что лучший способ сделать это – использовать команду SET ROWCOUNT перед оператором SELECT.

Итак, для вас:

 SET ROWCOUNT 1 SELECT %s FROM %s 

LIMIT стал довольно популярен среди различных баз данных с открытым исходным кодом, но, к сожалению, факт заключается в том, OFFSET разбиение на страницы OFFSET было связано с наименее стандартизированной функцией SQL для всех, стандартизированной уже в SQL: 2008 .

До тех пор, страница руководства пользователя jOOQ в предложении LIMIT показывает, как различные эквивалентные утверждения могут быть сформированы на каждом диалекте SQL:

 -- MySQL, H2, HSQLDB, Postgres, and SQLite SELECT * FROM BOOK LIMIT 1 OFFSET 2 -- CUBRID supports a MySQL variant of the LIMIT .. OFFSET clause SELECT * FROM BOOK LIMIT 2, 1 -- Derby, SQL Server 2012, Oracle 12c, SQL:2008 standard -- Some need a mandatory ORDER BY clause prior to OFFSET SELECT * FROM BOOK [ ORDER BY ... ] OFFSET 2 ROWS FETCH NEXT 1 ROWS ONLY -- Ingres SELECT * FROM BOOK OFFSET 2 FETCH FIRST 1 ROWS ONLY -- Firebird SELECT * FROM BOOK ROWS 2 TO 3 -- Sybase SQL Anywhere SELECT TOP 1 ROWS START AT 3 * FROM BOOK -- DB2 (without OFFSET) SELECT * FROM BOOK FETCH FIRST 1 ROWS ONLY -- Sybase ASE, SQL Server 2008 (without OFFSET) SELECT TOP 1 * FROM BOOK 

Теперь все это было довольно прямолинейно, не так ли? Здесь идет неприятная часть, когда вам нужно подражать им:

 -- DB2 (with OFFSET), SQL Server 2008 (with OFFSET), SELECT * FROM ( SELECT BOOK.*, ROW_NUMBER() OVER (ORDER BY ID ASC) AS RN FROM BOOK ) AS X WHERE RN > 2 AND RN <= 3 -- DB2 (with OFFSET), SQL Server 2008 (with OFFSET) -- When the original query uses DISTINCT! SELECT * FROM ( SELECT DISTINCT BOOK.ID, BOOK.TITLE DENSE_RANK() OVER (ORDER BY ID ASC, TITLE ASC) AS RN FROM BOOK ) AS X WHERE RN > 2 AND RN <= 3 -- Oracle 11g and less SELECT * FROM ( SELECT b.*, ROWNUM RN FROM ( SELECT * FROM BOOK ORDER BY ID ASC ) b WHERE ROWNUM <= 3 ) WHERE RN > 2 

Ознакомьтесь с ROW_NUMBER() и DENSE_RANK() здесь.

Выбери яд 😉

LIMIT очень далек от универсального – из основных РСУБД, он в значительной степени ограничен MySQL и PostgreSQL. Ниже приведен подробный анализ того, как это делается во многих других реализациях, включая MSSQL, Oracle и DB2, а также в ANSI SQL.

Это совсем не универсально. На самом деле я удивлен, что он работает для вас в Oracle; он не присутствовал. Обычно пользователи Oracle используют ROWNUM .

Каждая база данных имеет свой собственный синтаксис для ограничения результатов по номеру строки. Существуют также два метода, которые являются стандартными SQL ANSI:

  1. FETCH FIRST . Производится из DB / 2 и только стандартизован в SQL: 2008, поэтому очень мало поддержки СУБД. Невозможно использовать смещение.

  2. Функция windowing SELECT ..., ROW_NUMBER() OVER (ORDER BY some_ordering) AS rn WHERE rn BETWEEN n AND m ... ORDER BY some_ordering . Это от SQL: 2003 и имеет некоторую (неоднородную, иногда медленную) поддержку в новых СУБД. Он может использовать смещение или любую другую функцию сравнения для номера строки, но имеет недостаток в ужасающем уродстве.

Вот хороший обзор утомительности, с которой вам придется иметь дело, если вам нужна поддержка постраничной привязки между СУБД.

Он не работает на MSSQL (который вместо этого использует SELECT TOP 10 * FROM Blah ). Это сокращает значительную часть рынка БД. Я не уверен в других.

Кроме того, возможно, хотя и очень маловероятно, что ваш DB API переведет его для вас.

LIMIT не является частью стандарта ANSI SQL по стандарту 1992 года; У меня нет копии какого-либо более позднего стандарта. В лучшем случае соблюдение стандартов поставщиками довольно смутно. Для чего это стоит, «LIMIT» указан как зарезервированное слово (это означает, что он не может быть юридически использован как идентификатор даже в тех случаях, когда он не является ключевым словом в реализации).