Ограничение числа возвращаемых строк

Задача

Требуется ограничить число возвращаемых запросом строк. Порядок не имеет значения; подойдут любые n строк.

Решение

В Oracle ограничение на количество возвращаемых строк накладывается с помощью функции ROWNUM в предикате WHERE:

select e.*
from emp e
where rownum <= 5


EMPNO ENAME      JOB        MGR HIREDATE  SAL COMM DEPTNO
----- ---------- ---------- --- --------- --- ---- ------
 7369 SMITH      CLERK      7902 17-DEC-80 800          20
 7499 ALLEN      SALESMAN   7698 20-FEB-81 1600  300     30
 7521 WARD       SALESMAN   7698 22-FEB-81 1250  500     30
 7566 JONES      MANAGER    7839 02-APR-81 2975          20
 7654 MARTIN     SALESMAN   7698 28-SEP-81 1250 1400     30

Обсуждение

Для ограничения числа возвращаемых строк в Oracle приходится использовать функцию ROWNUM, возвращающую порядковый номер каждой строки результирующего множества (возвращающую, начиная с 1, величину).

Рассмотрим, то происходит при использовании ROWNUM <= 5 для возвращения первых пяти строк:

  1. Oracle выполняет запрос.
  2. Oracle извлекает первую строку и называет ее строкой номер 1.
  3. Номер строки больше 5? Если нет, Oracle возвращает строку, потому что она отвечает критерию: ее порядковый номер меньше или равен 5. Если да, Oracle не возвращает строку.
  4. Oracle извлекает следующую строку и присваивает ей слудущий порядковый номер по возрастанию (2, затем 3, затем 4 и т.д.).
  5. Переходим к шгу 3.

Как видно из данного процесса, присвоение значений, возвращаемых функцией ROWNUM, происходит после извлечения очередной строки. Это очень важно и является ключевым моментом. Многие разработчики на Oracle пытаются реализовать извлечение только, скажем, пятой возвращенной запросом строки, задавая ROWNUM = 5. Такое использование условия равенства в сочетании с ROWNUM является неверным. При попытке возвратить пятую строку с помощью ROWNUM = 5 роисходит следующее:

  1. Oracle выполняет запрос.
  2. Oracle извлекает первую строку и называет ее строкой номер 1.
  3. Номер строки равен 5? Если нет, Oracle отбрасывает строку, потому что она не отвечает заданному критерию. Если да, Oracle возвращает строку. Но ответ всегда будет отрицательным!
  4. Oracle извлекает следующую строку и называет ее строкой номер 1, поскольку первая возвращенная запросом строка должна быть пронумерована как первая строка.
  5. Переходим к шагу 3.

После тщательного разбора этого процесса становится понятно, почему использование ROWNUM = 5 не обеспечивает возвращения пятой строки. Невозможно получить пятую строку, не возвратив перед этим строки с первой по четвертую!

Однако заметьте, что с помощью ROWNUM = 1 можно получить первую строку. Может показаться, что это противоречит приведенному выше объяснению. Причина, почему ROWNUM = 1 обеспечивает возвращени первой строки, в том, что Oracle для определения наличия строк в таблице приходится извлекать, по крайней мере, одну из них. Внимательно проанализируйте предыдущий процесс, подставив 1 вместо 5, и вы поймете, почему для возвращения одной строки можно в качестве условия задавать ROWNUM = 1.