CYCLE в Oracle SQL — как находить циклы в иерархических запросах

🟢 CYCLE в Oracle SQL. Введение

Иерархические запросы в Oracle SQL — мощный инструмент для работы с древовидными структурами: отделами, категориями, задачами и т.д. Но они могут стать опасными, если в структуре появляются циклы — то есть «ребёнок» ссылается на своего «предка».

Именно здесь в игру вступает оператор CYCLE, который позволяет обнаруживать и помечать циклические зависимости в иерархических запросах с помощью CONNECT BY.


🔤 Написание

sql
SELECT ...
FROM таблица
CONNECT BY ...
CYCLE столбец_идентификатор
SET флаг_цикла TO значение_флага DEFAULT значение_по_умолчанию;

🔄 Где используется

  • В иерархических структурах с потенциальными замыканиями

  • В системах с неявной рекурсией (категории, подкатегории)

  • Для избежания бесконечной рекурсии в CONNECT BY

  • В графовых и сетевых моделях хранения данных

  • Для анализа бизнес-логики с ошибками связей


🧪 10 Примеров использования CYCLE

1️⃣ Базовая структура с CONNECT BY

sql
SELECT employee_id, manager_id
FROM employees
CONNECT BY PRIOR employee_id = manager_id;

2️⃣ Добавление CYCLE для предотвращения зацикливания

sql
SELECT employee_id, manager_id, is_cycle
FROM employees
CONNECT BY PRIOR employee_id = manager_id
CYCLE employee_id SET is_cycle TO 'Y' DEFAULT 'N';

Если сотрудник замкнулся на самого себя — будет Y.


3️⃣ Поиск только циклов

sql
SELECT *
FROM (
SELECT employee_id, is_cycle
FROM employees
CONNECT BY PRIOR employee_id = manager_id
CYCLE employee_id SET is_cycle TO 'Y' DEFAULT 'N'
)
WHERE is_cycle = 'Y';

4️⃣ Именование флага цикла

sql
CYCLE department_id SET loop_flag TO 'CYCLE' DEFAULT 'OK';

5️⃣ Использование флага в логике

sql
SELECT department_id,
CASE loop_flag
WHEN 'CYCLE' THEN 'Ошибка структуры'
ELSE 'Нормально'
END AS статус
FROM ...

6️⃣ Пример с родителями и детьми (parent_id)

sql
SELECT id, parent_id, is_loop
FROM categories
CONNECT BY PRIOR id = parent_id
CYCLE id SET is_loop TO 'Y' DEFAULT 'N';

7️⃣ Формирование древовидного отчёта с флагом

sql
SELECT LPAD(' ', LEVEL * 2) || name AS структура, is_loop
FROM org_units
CONNECT BY PRIOR unit_id = parent_id
CYCLE unit_id SET is_loop TO 'Y' DEFAULT 'N';

8️⃣ Вывод глубины и наличия цикла

sql
SELECT name, LEVEL, is_cycle
FROM items
CONNECT BY PRIOR item_id = parent_id
CYCLE item_id SET is_cycle TO 'Y' DEFAULT 'N';

9️⃣ Создание искусственного цикла (пример)

sql
INSERT INTO employees (employee_id, manager_id)
VALUES (999, 999);

Создаёт цикл: сотрудник — сам себе начальник.


🔟 Защита от цикла через фильтр

sql
SELECT *
FROM employees
CONNECT BY PRIOR employee_id = manager_id
CYCLE employee_id SET cyc_flag TO 'Y' DEFAULT 'N'
HAVING cyc_flag = 'N';

🧩 Заключение

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

💡 Запомни:

  • CYCLE не останавливает выполнение — он отмечает проблему

  • Используй SET ... TO ... DEFAULT ... для удобного флага

  • Особенно полезен при анализе данных от пользователей или внешних источников


🔜 Следующая статья:

CURRENT в Oracle SQL — как использовать текущие значения курсора, даты и временных зон


Понравилась статья? Поделиться с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии