Найти в Дзене
Oracle Developer

Псевдостолбец ROWNUM в Oracle: тонкости и подводные камни

Оглавление

Если вы работали с Oracle SQL, то наверняка встречали псевдостолбец ROWNUM. Многие разработчики на первых порах думают, что это аналог порядкового номера строки в результате запроса, но не всё так просто. Давайте разберёмся, как он работает и когда его лучше заменить на ROW_NUMBER().

Что такое ROWNUM?

ROWNUM — это число, которое Oracle назначает каждой строке по мере их выборки в запросе. Это не окончательный порядковый номер строки в итоговом результате, а скорее номер, который присваивается в процессе выполнения запроса.

💡 Важно понимать: ROWNUM всегда назначается до сортировки (ORDER BY). Поэтому, если вы попробуете использовать ROWNUM для получения первых N отсортированных записей, результат может быть неожиданным.

Порядок выполнения запроса в Oracle

Чтобы понять, почему ROWNUM ведёт себя именно так, разберём порядок обработки SQL-запроса:

1️⃣ FROM/WHERE — выбираются строки из таблицы и фильтруются условия.

2️⃣ ROWNUM — каждой строке присваивается порядковый номер в том порядке, в котором Oracle их получает.

3️⃣ SELECT — выполняются проекции и вычисления.

4️⃣ GROUP BY — группировка строк (если есть).

5️⃣ HAVING — фильтрация группированных данных.

6️⃣ ORDER BY — финальная сортировка.

📌 Вывод: ROWNUM назначается до сортировки. Это ключевой момент, который часто становится причиной ошибок.

Почему ROWNUM не работает с сортировкой?

Рассмотрим пример:

SELECT * FROM employees WHERE ROWNUM <= 5 ORDER BY salary DESC;

❌ Этот запрос не вернёт 5 сотрудников с самой высокой зарплатой. ROWNUM назначается перед ORDER BY, а значит, выберутся первые 5 строк в случайном порядке, а потом они отсортируются.

Как сделать правильно?

Обходные пути

Вариант 1: Подзапрос

SELECT * FROM (
SELECT * FROM employees ORDER BY salary DESC
) WHERE ROWNUM <= 5;

Теперь сначала выполняется сортировка, а затем ROWNUM корректно выбирает верхние 5 записей.

Вариант 2: Аналитическая функция ROW_NUMBER()

SELECT * FROM (
SELECT employees.*, ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn
FROM employees
) WHERE rn <= 5;

Здесь мы используем ROW_NUMBER(), которая присваивает номер уже после сортировки, что даёт правильный результат.

Итог

🔹 ROWNUM не подходит для нумерации строк в отсортированном наборе данных.

🔹 Если нужна сортировка — используйте ROW_NUMBER() OVER(...).

🔹 При необходимости выбрать N записей после сортировки, оборачивайте запрос в подзапрос.

Использовали ли вы ROWNUM неправильно? Делитесь своими историями в комментариях! 👇

----------

Хотите разбираться в таких вещах на экспертном уровне? На нашем YouTube-канале мы регулярно разбираем подобные темы, а в Telegram-канале можно задать вопросы и пообщаться с коллегами! Присоединяйтесь! 💡

А еще в нашей онлайн-школе мы проводим обучение по направлениям:🔸PL/SQL; 🔸оптимизация Oracle SQL; 🔸секционирование; 🔸архитектуре СУБД; 🔸Unit-тестированию и др.

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

Лицензия на дополнительное образование взрослых и детей Л035-01199-54/01691393 выдана 13.01.2025 г. Министерством образование Новосибирской области Российской Федерации

🔗 Полезные ссылки:

  • 📹 YouTube-канал: Oracle DBD
  • 📢 Telegram-канал: Oracle Developer
  • ✉️ Написать автору канала (Денис): @denis_dbd

    #Oracle #PLSQL #БазыДанных #Разработка #SQL #Программирование #ITсоветы #ROWNUM #ROW_NUMBER #Лайфхаки