Пейджинг с Oracle

74

Я не так хорошо знаком с Oracle, каким хотел бы быть. У меня есть записи 250 тыс., И я хочу отображать их по 100 на страницу. В настоящее время у меня есть одна хранимая процедура, которая извлекает все четверть миллиона записей в набор данных с использованием адаптера данных и набора данных, а также метод dataadapter.Fill(набор данных) по результатам хранимой процедуры. Если у меня есть "Номер страницы" и "Количество записей на странице" в качестве значений целого числа, которые я могу передать в качестве параметров, что было бы лучшим способом вернуть именно этот конкретный раздел. Скажем, если я передам 10 в качестве номера страницы, а 120 - как количество страниц, из предложения select это даст мне 1880-е по 1200-й, или что-то в этом роде, моя математика в моей голове может быть выключена.

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

Обновление: я смог использовать предложение Брайана, и он отлично работает. Я хотел бы поработать над некоторой оптимизацией, но страницы появляются в течение 4-5 секунд, а не через минуту, и мой пейджинговый контроль смог очень хорошо интегрироваться с моими новыми хранимыми процедурами.

Теги:
stored-procedures

5 ответов

104
Лучший ответ

Что-то вроде этого должно работать: Из журнала Frans Bouma

SELECT * FROM
(
    SELECT a.*, rownum r__
    FROM
    (
        SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%'
        ORDER BY OrderDate DESC, ShippingDate DESC
    ) a
    WHERE rownum < ((pageNumber * pageSize) + 1 )
)
WHERE r__ >= (((pageNumber-1) * pageSize) + 1)
  • 1
    Является ли rownum зарезервированным словом?
  • 4
    Да, это «встроенный» столбец, который поддерживает Oracle, он всегда начинается с 1 и увеличивается для каждой строки. Таким образом, в этом фрагменте кода, если у вас есть 1000 строк, применяется порядок сортировки, а затем каждой строке присваивается rownum. Внешний выбор (ы) использует эти номера строк, чтобы найти «страницу», которую вы ищете, основываясь на вашем размере страницы.
Показать ещё 7 комментариев
114

Спросите у Тома о разделении страниц и очень, очень полезных аналитических функциях.

Это выдержка из этой страницы:

select * from (
    select /*+ first_rows(25) */
     object_id,object_name,
     row_number() over
    (order by object_id) rn
        from all_objects)
    where rn between :n and :m
        order by rn;
  • 5
    На самом деле это гораздо лучшая реализация, хотя ее трудно найти в этом посте. Если у вас много больших страниц, другой ответ также должен пройти по всем строкам предыдущих страниц. В сложных запросах это означает, что более поздние страницы работают хуже, чем более ранние.
  • 0
    @tallseth Ты прав. Трудно найти это на этой странице. Выдержка добавлена.
Показать ещё 1 комментарий
30

В интересах полноты, для людей, которые ищут более современное решение, в Oracle 12c есть несколько новых функций, включая улучшенную подкачку и верхнюю обработку.

Paging

Пейджинг выглядит следующим образом:

SELECT *
FROM user
ORDER BY first_name
OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY;

Лучшие записи N

Получение верхних записей выглядит следующим образом:

SELECT *
FROM user
ORDER BY first_name
FETCH FIRST 5 ROWS ONLY

Обратите внимание на то, что оба приведенных выше примера запроса имеют предложения ORDER BY. Новые команды уважают их и запускаются на отсортированные данные.

Я не мог найти хорошую страницу ссылок Oracle для FETCH или OFFSET, но эта страница имеет большой обзор этих новых функций.

  • 0
    Это отличный ответ для пользователей 12с
  • 0
    Синтаксис чище, но производительность хуже ( dba-presents.com/index.php/databases/oracle/… )
Показать ещё 1 комментарий
5

Просто хочу обобщить ответы и комментарии. Существует несколько способов сделать разбивку на страницы.

До оракула 12c не было функциональности OFFSET/FETCH, поэтому посмотрите на технический документ, как предлагал @jasonk. Это самая полная статья, которую я нашел о различных методах с подробным объяснением преимуществ и недостатков. Это займет много времени, чтобы скопировать их здесь, поэтому я не буду этого делать.

Существует также хорошая статья от создателей jooq, объясняющих некоторые общие оговорки с разбиением на оракулы и другие базы данных. jooq blogpost

Хорошие новости, так как оракул 12c имеет новую функциональность OFFSET/FETCH. Новые возможности OracleMagazine 12c. См. "Самые популярные запросы и разбивка на страницы"

Вы можете проверить версию oracle, выпустив следующую инструкцию

SELECT * FROM V$VERSION
3

Попробуйте следующее:

SELECT *
FROM
  (SELECT FIELDA,
    FIELDB,
    FIELDC,
    ROW_NUMBER() OVER (ORDER BY FIELDC) R
  FROM TABLE_NAME
  WHERE FIELDA = 10
  )
WHERE R >= 10
AND R   <= 15;

через [tecnicume]

Ещё вопросы

Сообщество Overcoder
Наверх
Меню