Как ROWNUM работает в запросе на нумерацию страниц?

Поэтому я хочу выбрать диапазон строк в БД Oracle. Я должен сделать это, потому что у меня есть миллионы строк в таблице, и я хочу разбить результаты на пользователя (если вы знаете другой способ сделать это на стороне клиента, я использую JavaFX, если это важно, но я не делаю думаю, что это хорошая идея, чтобы отправить все данные по сети, чтобы разбить их на страницы на стороне клиента).

Итак, после прочтения этого поста: SQL ROWNUM, как вернуть строки между определенным диапазоном, у меня есть следующий запрос:

Select * From (Select t.*, rownum r from PERSON t) Where r > 100 and r < 110;

100 а также 110 просто пример. В приложении я просто запрашиваю нижнюю границу и добавляю размер 10_000 для выборки следующих 10_000 строк.

Теперь столбец rownum появляется в результате, и я не хочу его видеть. Поскольку я не очень разбираюсь в SQL, вот мои вопросы:

  1. Почему (это была моя первая попытка, пока я не поищу на SO) Select * From Person Where rownum > 100 and rownum < 110; возвращает 0 строк?
  2. Почему нет простого способа сделать что-то вроде Select ... FROM ... WHERE rownum BETWEEN lowerBound AND upperBound?

  3. Как избавиться от r столбец в результирующих значениях? Оттуда SQL исключает столбец, используя SELECT * [кроме columnA] FROM tableA? По-видимому, мне нужно создать представление или временную таблицу, но есть ли другой способ рассмотреть мой запрос?

  4. Обеспечивает ли это правильную нумерацию страниц? Я прочитал этот раздел статьи "Разбиение на страницы с ROWNUM", в котором говорилось, что я должен упорядочить значения по чему-то уникальному, чтобы получить последовательную нумерацию страниц (так что я думаю, упорядочение по rownum хорошо, если вы можете подтвердить). Разве это не противоречит цели использования FIRST_ROWS(N)?

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

Спасибо:)

3 ответа

Решение

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

Почему (это была моя первая попытка, пока я не поищу на SO) Выберите * From Person Where rownum > 100 и rownum < 110; возвращает 0 строк?

Хорошее объяснение Томаса Кайта относительно ROWNUM и нумерации страниц здесь.

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

select * 
  from t 
 where ROWNUM > 1;

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

Почему нет простого способа сделать что-то вроде Select ... FROM ... WHERE rownum МЕЖДУ lowerBound И upperBound?

Да, есть. Начиная с Oracle 12c, вы можете использовать новую функцию ограничения Top-n Row. Смотрите мой ответ здесь.

Например, приведенный ниже запрос вернет сотрудникам от 4-й до 7-й зарплаты в порядке возрастания:

SQL> SELECT empno, sal
  2  FROM   emp
  3  ORDER BY sal
  4  OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY;

     EMPNO        SAL
---------- ----------
      7654       1250
      7934       1300
      7844       1500
      7499       1600

SQL>

Как избавиться от столбца r в результирующих значениях?

Вместо select *, перечислите необходимые имена столбцов во внешнем запросе. Для частого использования запроса создание представления является простым одноразовым действием.

В качестве альтернативы, в SQL*Plus Вы можете использовать команду NOPRINT. Он не будет отображать имя столбца, который вы не хотите отображать. Тем не менее, это будет работать только в SQL*Plus.

Например,

COLUMN column_name NOPRINT

Например,

SQL> desc dept
 Name                                      Null?    Type
 ----------------------------------------- -------- ------------
 DEPTNO                                             NUMBER(2)
 DNAME                                              VARCHAR2(14)
 LOC                                                VARCHAR2(13)

SQL> COLUMN dname NOPRINT
SQL> COLUMN LOC NOPRINT
SQL> SELECT * FROM dept;

    DEPTNO
----------
        10
        20
        30
        40

SQL>

Обеспечивает ли это правильную нумерацию страниц?

Да, если вы правильно написали запрос на нумерацию страниц.

Например,

SELECT val
FROM   (SELECT val, rownum AS rnum
        FROM   (SELECT val
                FROM   t
                ORDER BY val)
        WHERE rownum <= 8)
WHERE  rnum >= 5;

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

4 rows selected.

SQL>

Или используйте новую функцию ограничения строк на 12c, как я показал выше.

Несколько хороших примеров здесь.

Ответ на вопрос 2: В Oracle 12 вы можете использовать нумерацию страниц

select owner, object_name, object_id
from t
order by owner, object_name
OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY;

Я обычно пишу запрос так:

select * 
from 
(
    select a.*, rownum as rn  
    from table_name a
    where rownum <= 110
)
where rn > 100 
Другие вопросы по тегам