Думата dep
във втората заявка (след union
) е двусмислено. Всъщност тя се интерпретира като колоната на rdeps
, а не като псевдоним на objectdependencies.
with recursive rdeps as (
select dep
from objectdependencies dep
where dep.dependson = 4 -- starting point
union all
select dep -- this means r.dep
from objectdependencies dep
join rdeps r
on (r.dep).id = dep.dependson
) select (dep).id from rdeps;
Ето защо заявката създава безкраен цикъл. Можете да коригирате това, като промените псевдонима:
with recursive rdeps as (
select dep
from objectdependencies dep
where dep.dependson = 4 -- starting point
union all
select objectdep
from objectdependencies objectdep
join rdeps r
on (r.dep).id = objectdep.dependson
) select (dep).id from rdeps;
id
----
1
2
3
1
2
1
(6 rows)
Или по-добре, просто като използвате колони, както е замислил добрият Господ:
with recursive rdeps as (
select id, dependson
from objectdependencies
where dependson = 4
union all
select d.id, d.dependson
from objectdependencies d
join rdeps r
on r.id = d.dependson
)
select *
from rdeps;
Първата заявка във въпроса е всичко, което можете да направите в обикновен sql, тъй като няма комуникация между различни (паралелни) клонове, генерирани от рекурсивна заявка. При функционален подход можете да използвате временна таблица като общ магазин за всички клонове. Функцията може да изглежда така:
create or replace function rec_function(int)
returns void language plpgsql as $$
declare
i int;
begin
for i in
select id
from objectdependencies
where dependson = $1
loop
if not exists(
select from temp_table
where id = i)
then
insert into temp_table values(i);
perform rec_function(i);
end if;
end loop;
end $$;
Употреба:
create temp table temp_table(id int);
select rec_function(4);
select *
from temp_table;