Как ограничить количество строк, возвращаемых запросом Oracle после заказа?

Есть ли способ заставить запрос Oracle вести себя так, как будто он содержит предложение MySQL limit?

В MySQL я могу сделать это:

select * 
from sometable
order by name
limit 20,10

чтобы получить с 21-го по 30-й ряды (первые 20 пропустить, дать следующие 10). Строки выбираются после order by, поэтому он действительно начинается с 20-го имени по алфавиту.

В Oracle единственное, что упоминают, - это псевдостолбец rownum, но он оценивается как передorder by, что означает следующее:

select * 
from sometable
where rownum <= 10
order by name

вернет случайный набор из десяти строк, упорядоченных по имени, что обычно не то, что мне нужно. Он также не позволяет указывать смещение.

Стандартизирован в SQL: 2008.

dalle 26.01.2009 17:18

Похоже, что смещение и row_count поменялись местами в вашем первом примере MySQL. Этот запрос выберет строки с 11 по 30, а не с 21 по 30.

volni 21.06.2011 18:47

Лимит был объявлен Томом Кайтом для Oracle 12c ...

wolφi 03.12.2012 15:44

Считайте это оффтопом, но я с трудом могу представить реальные варианты использования, когда вам нужно извлечь данные из середины набора данных. Без шуток. Может, мне просто повезло, что я еще не подошел к таким требованиям. Если бы кто-то мог привести пример, основанный на реальном опыте ...

Yaroslav Shabalin 10.12.2013 01:43

Получение следующей страницы в наборе результатов?

Mathieu Longtin 16.12.2013 20:33

@YaroslavShabalin В частности, постраничный поиск использует этот шаблон все время. Практически любое приложение с любой функцией поиска будет использовать его. Другой вариант использования - загрузка только части длинного списка или таблицы на стороне клиента и предоставление пользователю возможности расширения.

jpmc26 14.08.2014 23:19

@MathieuLongtin @ jpmc26 В Google вы сначала начинаете со страницы номер 10? Зачем нужно выполнять запрос каждый раз, когда загружается следующая страница, если вы можете выполнить его один раз, открыть курсор и перемещаться, загружая определенную часть набора данных? Да, вам придется иметь дело с управлением памятью, если набор результатов большой, но избегайте возможной несогласованности. Учтите, что количество строк в наборе результатов меняется, каждый раз, когда вы повторно запрашиваете с помощью вышеуказанного limit 20,10, вы можете получить другой результат.

Yaroslav Shabalin 15.08.2014 12:47

@YaroslavShabalin Вы не можете получить другой набор результатов, если базовые данные не изменятся из-за ORDER BY. В этом весь смысл заказа. Если базовые данные изменяются и из-за этого изменяется ваш набор результатов, то почему бы не показать пользователю обновленные результаты вместо устаревшей информации? Кроме того, государственное управление - это чума, которую следует избегать как можно больше. Это постоянный источник проблем и ошибок; вот почему функциональность становится такой популярной. И когда вы узнаете, что срок действия всего набора результатов в памяти истекает? В сети у вас нет возможности узнать, когда пользователь уходит.

jpmc26 15.08.2014 19:03

@ jpmc26 Хорошо, я понял вашу точку зрения. Теперь это имеет смысл.

Yaroslav Shabalin 16.08.2014 08:11

@YaroslavShabalin - открытие курсора и удерживание его открытым в течение длительного периода времени в многопользовательском сценарии - хороший способ связать реляционную базу данных в узлы. В однопользовательской базе данных это, вероятно, не имеет значения, но когда у вас есть сотни одновременных подключений, это, скорее всего, приведет к проблемам. Реляционные базы данных обычно проектируются как транзакционные базы данных с относительно короткой продолжительностью транзакции. YMMV. Делитесь и наслаждайтесь.

Bob Jarvis - Reinstate Monica 18.08.2014 00:18

См. Как работает пагинация в Oracle SQL

Lalit Kumar B 21.01.2018 17:13

См. Также Пейджинг с Oracle

Vadzim 24.04.2018 20:56
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1 104
12
1 617 635
15
Перейти к ответу Данный вопрос помечен как решенный

Ответы 15

Вы можете использовать для этого подзапрос, например

select *
from  
( select * 
  from emp 
  order by sal desc ) 
where ROWNUM <= 5;

Также посмотрите тему О ROWNUM и ограничивающих результатах на Oracle / AskTom для получения дополнительной информации.

Обновлять: Чтобы ограничить результат как нижними, так и верхними границами, все становится немного более раздутым с

select * from 
( select a.*, ROWNUM rnum from 
  ( <your_query_goes_here, with order by> ) a 
  where ROWNUM <= :MAX_ROW_TO_FETCH )
where rnum  >= :MIN_ROW_TO_FETCH;

(Скопировано из указанной АскТом-статьи)

Обновление 2: Начиная с Oracle 12c (12.1) доступен синтаксис для ограничения строк или начала смещения.

SELECT * 
FROM   sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

См. Дополнительные примеры в этот ответ. Спасибо Крумии за подсказку.

Это определенно способ сделать это, но имейте в виду (как говорится в статье ask tom), что производительность запроса ухудшается по мере увеличения вашего max rownum. Это хорошее решение для результатов запроса, когда вы хотите видеть только первые несколько страниц, но если вы используете это как механизм для постраничного просмотра кода всей таблицы, вам лучше провести рефакторинг вашего кода.

Chris Gill 27.08.2009 16:30

+1 ваша нижняя / верхняя версия действительно помогла мне обойти проблему, когда простое предложение rownum с ограничением сверху резко замедляло мой запрос.

Kelvin 10.08.2011 02:21

"Аналитическое решение только с одним вложенным запросом" Ли Риффеля является единственным.

Darren Hicks 28.03.2012 03:22

В статье AskTom также есть подсказка оптимизатора, в которой используется SELECT / * + FIRST_ROWS (n) / а., rownum rnum Закрывающая косая черта должна предшествовать звездочке. ТАК вычищает это.

David Mann 05.03.2013 19:34

Обратите внимание, что для Oracle 11 внешний SELECT с ROWNUM не позволит вам вызвать deleteRow для UpdatableResultSet (с ORA-01446) - с нетерпением жду этого изменения 12c R1!

nsandersen 11.05.2015 11:34

В первом запросе разве внутренний запрос не должен извлекать все строки, прежде чем внешний сможет отфильтровать все, кроме первых пяти?

Tulains Córdova 02.12.2015 15:48

В отличие от подхода FETCH NEXT n ROWS, подзапрос с ограничением ROWNUM применим вместе с предложением FOR UPDATE.

nrainer 26.04.2020 12:07

Первый запрос также полезен, потому что сохраняется исходный набор столбцов. В средах, где результат запроса впоследствии обрабатывается каким-либо инструментом ORM, необходимо получить столбцы п из таблицы t.*, а не столбцы п + 1, включая какой-то переименованный rownum. Нестандартный пункт select * except rnum решил бы эту проблему, однако очень немногие базы данных поддерживают его на данный момент AFAIK. Кроме того, решение на основе rownum легко работает только для имитации условия limit. Эмулировать предложение offset сложнее из-за времени вычисления rownum (можно обойти, используя обратный порядок).

Tomáš Záluský 23.06.2020 10:02

(непроверено) что-то вроде этого может сработать

WITH
base AS
(
    select *                   -- get the table
    from sometable
    order by name              -- in the desired order
),
twenty AS
(
    select *                   -- get the first 30 rows
    from base
    where rownum < 30
    order by name              -- in the desired order
)
select *                       -- then get rows 21 .. 30
from twenty
where rownum > 20
order by name                  -- in the desired order

Существует также ранг аналитической функции, который можно использовать для сортировки.

Это не вернет ни одной строки, поскольку ROWNUM является столбцом в наборе результатов, поэтому последнее условие WHERE всегда будет ложным. К тому же вы не можете использовать ROWNUM и ЗАКАЗ ПО ГАРАНТИЙНОМУ ЗАКАЗУ.

Ben 08.09.2013 16:20

Отлично. Оставим это здесь как предупреждение другим.

EvilTeach 21.01.2014 19:33

Аналитическое решение с одним вложенным запросом:

SELECT * FROM
(
   SELECT t.*, Row_Number() OVER (ORDER BY name) MyRow FROM sometable t
) 
WHERE MyRow BETWEEN 10 AND 20;

Rank() можно заменить на Row_Number(), но он может вернуть больше записей, чем вы ожидаете, если есть повторяющиеся значения для имени.

Я люблю аналитику. Возможно, вы захотите уточнить, в чем разница в поведении между Rank () и Row_Number ().

Dave Costa 23.01.2009 19:53

Действительно, не знаю, почему я не подумал о дубликатах. Итак, в этом случае, если есть повторяющиеся значения для имени, тогда RANK может дать больше записей, чем вы ожидаете, поэтому вы должны использовать Row_Number.

Leigh Riffel 26.01.2009 17:11

Если упомянуть rank(), также стоит отметить dense_rank(), который может быть более полезным для управления выводом, поскольку последний не «пропускает» числа, тогда как rank() может. В любом случае для этого вопроса лучше всего подходит row_number(). Еще один недостаток заключается в том, что этот метод применим к любой базе данных, которая поддерживает упомянутые функции.

Paul Maxwell 29.10.2017 03:34

Меньше операторов SELECT. Кроме того, меньшее потребление производительности. Кредиты на: [email protected]

SELECT *
    FROM   (SELECT t.*,
                   rownum AS rn
            FROM   shhospede t) a
    WHERE  a.rn >= in_first
    AND    a.rn <= in_first;

Кроме того, это совершенно неверный ответ. Вопрос касался ограничения ПОСЛЕ сортировки. Так что rownum должен быть вне подзапроса.

BitLord 18.09.2017 10:20

Я провел несколько тестов производительности для следующих подходов:

Асктом

select * from (
  select a.*, ROWNUM rnum from (
    <select statement with order by clause>
  ) a where rownum <= MAX_ROW
) where rnum >= MIN_ROW

Аналитический

select * from (
  <select statement with order by clause>
) where myrow between MIN_ROW and MAX_ROW

Короткая альтернатива

select * from (
  select statement, rownum as RN with order by clause
) where a.rn >= MIN_ROW and a.rn <= MAX_ROW

Полученные результаты

В таблице было 10 миллионов записей, сортировка производилась по неиндексированной строке даты и времени:

  • План объяснения показал одинаковое значение для всех трех вариантов выбора (323168)
  • Но победителем стал AskTom (за которым следуют аналитики).

На выбор первых 10 строк ушло:

  • AskTom: 28-30 секунд
  • Аналитический: 33-37 секунд
  • Короткая альтернатива: 110–140 секунд.

Выбор строк от 100000 до 100 010:

  • AskTom: 60 секунд
  • Аналитический: 100 секунд

Выбор строк от 9 000 000 до 9 000 010:

  • AskTom: 130 секунд
  • Аналитический: 150 секунд

Хорошо сделано. Вы пробовали короткую альтернативу с промежуточным звеном вместо> = и <=?

Mathieu Longtin 05.07.2011 18:55

@MathieuLongtin BETWEEN - это просто сокращение от >= AND <= (stackoverflow.com/questions/4809083/between-clause-versus-a‌ nd)

wweicker 20.10.2011 19:27

zeldi - На какой это версии? Oracle улучшила аналитическую производительность в версии 11.1. и 11.2.

Leigh Riffel 26.09.2012 16:03

@Leigh Riffel Это было 10.2.0.5; однажды я мог бы найти время и также проверить версию 11i.

zeldi 11.03.2013 13:17

Я провел несколько быстрых тестов и получил аналогичные результаты для 12c. Новый синтаксис offset имеет тот же план и производительность, что и аналитический подход.

Jon Heller 18.01.2014 08:17
myrow не определен
shinzou 04.04.2018 13:50

В Oracle 12c (см. Пункт об ограничении строк в Справочник по SQL):

SELECT * 
FROM sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

И, конечно же, им пришлось использовать совершенно другой синтаксис, чем все остальные.

Mathieu Longtin 25.09.2013 05:12

Ясно, что после того, как все остальные поставщики договорились о LIMIT в SQL: 2008, им пришлось взять листок из книги Microsoft и нарушить стандарт.

beldaz 25.09.2013 05:39

Интересно, что недавно я слышал, что самый последний стандарт включает этот синтаксис, так что, возможно, Oracle ввел его первым перед внедрением. Возможно он более гибкий, чем LIMIT ... OFFSET

beldaz 01.01.2014 03:08

@ Дерек: Да, несоблюдение стандарта прискорбно. Но недавно представленная функциональность в 12cR1 более мощная, чем просто LIMIT n, m (см. Мой ответ). С другой стороны, Oracle следовало бы реализовать LIMIT n, m как синтаксический сахар, поскольку он эквивалентен OFFSET n ROWS FETCH NEXT m ROWS ONLY.

sampathsris 26.09.2014 17:54

@Derek: На самом деле, я только что заметил это замечание в руководстве PostgreSQL postgresql.org/docs/9.0/static/sql-select.html#AEN69535 «Пункты LIMIT и OFFSET - это специфичный для PostgreSQL синтаксис, также используемый MySQL. Стандарт SQL: 2008 представил предложения OFFSET ... FETCH {FIRST | NEXT } ... для той же функциональности ". Так что LIMIT никогда не входил в стандарт.

beldaz 21.05.2015 03:58

@beldaz Я обнаружил, что ваша ссылка не работает (из-за изменения привязки?), собственно postgresql.org/docs/9.0/static/sql-select.html#AEN69605 (на данный момент, конечно ;-))

Wirone 23.10.2015 14:51

@Wirone: Пока: postgresql.org/docs/9.0/static/sql-select.html#SQL-LIMIT

sampathsris 08.03.2016 07:06

@Krumia Спасибо. Можно даже использовать www.postgresql.org/docs/current/static/sql-select.html#SQL-L‌ IMIT для самой последней версии

beldaz 08.03.2016 07:13

Помимо всех аргументов стандартизации, если вам просто нужно что-то, что работает для Oracle, по состоянию на 2014 год это лучший из всех ответов, ИМХО. +1

trpt4him 16.05.2016 16:30

Запросы пагинации с упорядочением в Oracle действительно сложны.

Oracle предоставляет псевдостолбец ROWNUM, который возвращает число, указывающее порядок, в котором база данных выбирает строку из таблицы или набора объединенных представлений.

ROWNUM - это псевдоколонка, из-за которой многие люди попадают в беду. Значение ROWNUM не присваивается строке постоянно (это распространенное заблуждение). Когда фактически присваивается значение ROWNUM, это может сбивать с толку. Значение ROWNUM присваивается строке после прохождения предикатов фильтра запроса, но перед агрегацией или сортировкой запросов.

Более того, значение ROWNUM увеличивается только после того, как оно присвоено.

Вот почему следующий запрос не возвращает строк:

 select * 
 from (select *
       from some_table
       order by some_column)
 where ROWNUM <= 4 and ROWNUM > 1; 

Первая строка результата запроса не передает предикат ROWNUM> 1, поэтому ROWNUM не увеличивается до 2. По этой причине ни одно значение ROWNUM не становится больше 1, следовательно, запрос не возвращает строк.

Правильно определенный запрос должен выглядеть так:

select *
from (select *, ROWNUM rnum
      from (select *
            from skijump_results
            order by points)
      where ROWNUM <= 4)
where rnum > 1; 

Узнайте больше о запросах пагинации в моих статьях в блоге Vertabelo:

Первая строка результата запроса не передает предикат ROWNUM> 1 (…) - голос за объяснение.
Piotr Dobrogost 13.03.2019 12:11
Ответ принят как подходящий

Начиная с Oracle 12c R1 (12.1), существует является и предложение, ограничивающее строку. В нем не используется знакомый синтаксис LIMIT, но он может работать лучше с большим количеством опций. Вы можете найти полный синтаксис здесь. (Также читайте больше о том, как это работает внутри Oracle в этот ответ).

Чтобы ответить на исходный вопрос, вот запрос:

SELECT * 
FROM   sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

(Для более ранних версий Oracle, пожалуйста, обратитесь к другим ответам в этом вопросе)


Примеры:

Следующие примеры были процитированы из связанная страница в надежде предотвратить гниение ссылок.

Настраивать

CREATE TABLE rownum_order_test (
  val  NUMBER
);

INSERT ALL
  INTO rownum_order_test
SELECT level
FROM   dual
CONNECT BY level <= 10;

COMMIT;

Что в таблице?

SELECT val
FROM   rownum_order_test
ORDER BY val;

       VAL
----------
         1
         1
         2
         2
         3
         3
         4
         4
         5
         5
         6
         6
         7
         7
         8
         8
         9
         9
        10
        10

20 rows selected.

Получить первые строки N

SELECT val
FROM   rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS ONLY;

       VAL
----------
        10
        10
         9
         9
         8

5 rows selected.

Получить первые строки N, если строка Nth имеет связи, получить все связанные строки

SELECT val
FROM   rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS WITH TIES;

       VAL
----------
        10
        10
         9
         9
         8
         8

6 rows selected.

Верхний CDD: 333% строк

SELECT val
FROM   rownum_order_test
ORDER BY val
FETCH FIRST 20 PERCENT ROWS ONLY;

       VAL
----------
         1
         1
         2
         2

4 rows selected.

Использование смещения, очень полезно для разбивки на страницы

SELECT val
FROM   rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY;

       VAL
----------
         3
         3
         4
         4

4 rows selected.

Вы можете комбинировать смещение с процентами

SELECT val
FROM   rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 20 PERCENT ROWS ONLY;

       VAL
----------
         3
         3
         4
         4

4 rows selected.

Просто для расширения: синтаксис OFFSET FETCH - это синтаксический сахар. Подробности

Lukasz Szozda 18.08.2019 22:03

Как мы можем получить LIMIT и OFFSET в Oracle 11G?

Pra_A 21.06.2020 16:37

@Pra_A В 11G нет встроенной поддержки LIMIT / OFFSET. Если вы проверите другие ответы, все они так или иначе фактически реализовали предел и смещение.

sampathsris 24.06.2020 09:11

Я начал подготовку к экзамену Oracle 1z0-047, подтвержденному на 12c Во время подготовки к нему я наткнулся на усовершенствование 12c, известное как FETCH FIRST. Это позволяет вам получать строки / ограничивать строки по вашему усмотрению. С ним доступны несколько вариантов

- FETCH FIRST n ROWS ONLY
 - OFFSET n ROWS FETCH NEXT N1 ROWS ONLY // leave the n rows and display next N1 rows
 - n % rows via FETCH FIRST N PERCENT ROWS ONLY

Пример:

Select * from XYZ a
order by a.pqr
FETCH FIRST 10 ROWS ONLY
stackoverflow.com/a/26051830/635608 - это уже было указано в других ответах. Пожалуйста, воздержитесь от публикации материалов, которые уже были опубликованы несколько месяцев назад.
Mat 01.06.2016 14:43

о, конечно, не перебирал все ответы, я рано натолкнулся на подзапросы, буду иметь это в виду.

arjun gaur 01.06.2016 15:48

Если вы не используете Oracle 12C, вы можете использовать запрос TOP N, как показано ниже.

SELECT *
 FROM
   ( SELECT rownum rnum
          , a.*
       FROM sometable a 
   ORDER BY name
   )
WHERE rnum BETWEEN 10 AND 20;

Вы даже можете переместить это предложение в предложение with следующим образом

WITH b AS
( SELECT rownum rnum
      , a.* 
   FROM sometable a ORDER BY name
) 
SELECT * FROM b 
WHERE rnum BETWEEN 10 AND 20;

На самом деле здесь мы создаем встроенное представление и переименовываем rownum в rnum. Вы можете использовать rnum в основном запросе в качестве критерия фильтрации.

В моем случае это не вернуло правильные строки. Чтобы исправить это, я сделал ORDER BY и rownum отдельно. В основном я создал подзапрос с предложением ORDER BY.

Patrick Gregorio 10.05.2018 23:28

Проголосуйте против, так как это неверный ответ. Вопрос касался ограничения после сортировки, поэтому rownum должен быть вне подзапроса.

Piotr Dobrogost 13.03.2019 12:06

@PiotrDobrogost rownum находится только снаружи.

sandi 30.09.2019 11:49
select * FROM (SELECT 
   ROW_NUMBER() OVER (ORDER BY sal desc),* AS ROWID, 
 FROM EMP ) EMP  where ROWID=5

больше значений узнать

select * FROM (SELECT 
       ROW_NUMBER() OVER (ORDER BY sal desc),* AS ROWID, 
     FROM EMP ) EMP  where ROWID>5

меньше значений узнают

select * FROM (SELECT 
       ROW_NUMBER() OVER (ORDER BY sal desc),* AS ROWID, 
     FROM EMP ) EMP  where ROWID=5

Голосовать против решения на основе ROW_NUMBER() уже опубликовал Ли Риффель. Кроме того, в показанном коде есть синтаксические ошибки.

Piotr Dobrogost 13.03.2019 11:33

Для каждой строки, возвращаемой запросом, псевдостолбец ROWNUM возвращает число, указывающее порядок, в котором Oracle выбирает строку из таблицы или набора соединенных строк. Первая выбранная строка имеет ROWNUM 1, вторая - 2 и так далее.

  SELECT * FROM sometable1 so
    WHERE so.id IN (
    SELECT so2.id from sometable2 so2
    WHERE ROWNUM <=5
    )
    AND ORDER BY so.somefield AND ROWNUM <= 100 

Я реализовал это на сервере oracle11.2.0.1.0

проголосуйте против, так как вопрос задает об ограничении строк упорядоченный, и у вас даже нет порядка

Piotr Dobrogost 13.03.2019 11:23

@PiotrDobrogost. Поймите, что это не такая уж большая задача, упорядочивание ключевых слов является общим для всех rdbms. Изменен только предел.

Sumesh TG 13.03.2019 11:48

Стандарт SQL

Начиная с версии 12c Oracle поддерживает стандарт SQL: 2008 Standard, который предоставляет следующий синтаксис для ограничения набора результатов SQL:

SELECT
    title
FROM
    post
ORDER BY
    id DESC
FETCH FIRST 50 ROWS ONLY

Oracle 11g и более ранние версии

До версии 12c для получения записей Top-N нужно было использовать производную таблицу и псевдостолбец ROWNUM:

SELECT *
FROM (
    SELECT
        title
    FROM
        post
    ORDER BY
        id DESC
)
WHERE ROWNUM <= 50

Как расширение принятый ответ Oracle внутренне использует функции ROW_NUMBER/RANK. Синтаксис OFFSET FETCH - это синтаксический сахар.

Это можно было наблюдать с помощью процедуры DBMS_UTILITY.EXPAND_SQL_TEXT:

Подготовка образца:

CREATE TABLE rownum_order_test (
  val  NUMBER
);

INSERT ALL
  INTO rownum_order_test
SELECT level
FROM   dual
CONNECT BY level <= 10;
COMMIT;

Запрос:

SELECT val
FROM   rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS ONLY;

регулярно:

SELECT "A1"."VAL" "VAL" 
FROM  (SELECT "A2"."VAL" "VAL","A2"."VAL" "rowlimit_$_0",
               ROW_NUMBER() OVER ( ORDER BY "A2"."VAL" DESC ) "rowlimit_$$_rownumber" 
      FROM "ROWNUM_ORDER_TEST" "A2") "A1" 
WHERE "A1"."rowlimit_$$_rownumber"<=5 ORDER BY "A1"."rowlimit_$_0" DESC;

db <> демо скрипта

Получение развернутого текста SQL:

declare
  x VARCHAR2(1000);
begin
 dbms_utility.expand_sql_text(
        input_sql_text => '
          SELECT val
          FROM   rownum_order_test
          ORDER BY val DESC
          FETCH FIRST 5 ROWS ONLY',
        output_sql_text => x);

  dbms_output.put_line(x);
end;
/

WITH TIES расширяется как RANK:

declare
  x VARCHAR2(1000);
begin
 dbms_utility.expand_sql_text(
        input_sql_text => '
          SELECT val
          FROM   rownum_order_test
          ORDER BY val DESC
          FETCH FIRST 5 ROWS WITH TIES',
        output_sql_text => x);

  dbms_output.put_line(x);
end;
/

SELECT "A1"."VAL" "VAL" 
FROM  (SELECT "A2"."VAL" "VAL","A2"."VAL" "rowlimit_$_0",
              RANK() OVER ( ORDER BY "A2"."VAL" DESC ) "rowlimit_$$_rank" 
       FROM "ROWNUM_ORDER_TEST" "A2") "A1" 
WHERE "A1"."rowlimit_$$_rank"<=5 ORDER BY "A1"."rowlimit_$_0" DESC

и смещение:

declare
  x VARCHAR2(1000);
begin
 dbms_utility.expand_sql_text(
        input_sql_text => '
          SELECT val
FROM   rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY',
        output_sql_text => x);

  dbms_output.put_line(x);
end;
/


SELECT "A1"."VAL" "VAL" 
FROM  (SELECT "A2"."VAL" "VAL","A2"."VAL" "rowlimit_$_0",
             ROW_NUMBER() OVER ( ORDER BY "A2"."VAL") "rowlimit_$$_rownumber" 
       FROM "ROWNUM_ORDER_TEST" "A2") "A1" 
       WHERE "A1"."rowlimit_$$_rownumber"<=CASE  WHEN (4>=0) THEN FLOOR(TO_NUMBER(4)) 
             ELSE 0 END +4 AND "A1"."rowlimit_$$_rownumber">4 
ORDER BY "A1"."rowlimit_$_0"

В случае SQL-Developer он автоматически выбирает только первые 50 строк. И если мы прокрутим вниз, получится еще 50 строк и так далее!

Следовательно, в случае инструмента sql-developer нам не нужно определять!

Другие вопросы по теме