Как 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, вот мои вопросы:
- Почему (это была моя первая попытка, пока я не поищу на SO)
Select * From Person Where rownum > 100 and rownum < 110;
возвращает 0 строк? Почему нет простого способа сделать что-то вроде
Select ... FROM ... WHERE rownum BETWEEN lowerBound AND upperBound
?Как избавиться от
r
столбец в результирующих значениях? Оттуда SQL исключает столбец, используя SELECT * [кроме columnA] FROM tableA? По-видимому, мне нужно создать представление или временную таблицу, но есть ли другой способ рассмотреть мой запрос?Обеспечивает ли это правильную нумерацию страниц? Я прочитал этот раздел статьи "Разбиение на страницы с 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