Простой пример употребления фразы WITH для построения рекурсивного запроса: WITH numbers ( n ) AS ( SELECT 1 AS n FROM dual -- исходное множество -- одна строка UNION ALL -- символическое «объединение» строк SELECT n + 1 AS n -- рекурсия: добавок к предыдущему результату FROM numbers -- предыдущий результат в качестве источника данных WHERE n < 5 -- если не ограничить, будет бесконечная рекурсия ) SELECT n FROM numbers -- основной запрос ;
Операция UNION ALL здесь используется символически, в рамках определенного контекста, для указания способа рекурсивного накопления результата.
Ответ: N ---------- 1 2 3 4 5
Строка с n = 1 получена из опорного запроса, а остальные строки из рекурсивного. Из примера видна оборотная сторона рекурсивных формулировок: при неаккуратном планировании они допускают «бесконечное» выполнение (на деле – пока хватит ресурсов СУБД для сеанса или же пока администратор не прервет запрос или сеанс). С фразой CONNECT BY «бесконечное» выполнение в принципе невозможно. Программист обязан отнестись к построению рекурсивного запроса ответственно.
Еще один вывод из этого примера: подобно случаю с CONNECT BY, вынесенный рекурсивный подзапрос применим вовсе необязательно только к иерархически организованным данным.
Пример с дополнительным разъяснением способа выполнения: SQL> WITH 2 anchor1234 ( n ) AS ( -- обычный 3 SELECT 1 FROM dual UNION ALL 4 SELECT 2 FROM dual UNION ALL 5 SELECT 3 FROM dual UNION ALL 6 SELECT 4 FROM dual 7 ) 8 , numbers ( n ) AS ( -- рекурсивный 9 SELECT n FROM anchor1234
10 UNION ALL 11 SELECT n + 1 AS n 12 FROM numbers
13 WHERE n < 5 14 ) 15 SELECT n FROM numbers
16 ;
N ---------- 1 ←опорный запрос 2 ←опорный запрос 3 ←опорный запрос 4 ←опорный запрос 2 ←рекурсия 1 3 ←рекурсия 1 4 ←рекурсия 1 5 ←рекурсия 1 3 ←рекурсия 2 4 ←рекурсия 2 5 ←рекурсия 2 4 ←рекурсия 3 5 ←рекурсия 3 5 ←рекурсия 4