PL-*_*000 6 sql postgresql plpgsql circular-reference postgresql-9.1
我有一张带有属性的表(ID int、SourceID int、TargetID int、TargetType int)
ID 源ID 目标ID -------------------- 1 123 456 2 456 789 3 1 123 4 456 1 5 2 1
我想找出所有循环引用。我想为此编写 PL/pgsql 函数。
这里 ID 4 的循环引用 = 456 1 123 456
我想找到这样的例子。谁能建议我如何进行此操作。
这可以通过下面的递归函数来完成。该函数使用intarray 扩展。
create extension intarray;
Run Code Online (Sandbox Code Playgroud)
int 数组的第一个元素arr是id。数组的其余部分包含连续的引用source -> target.
如果数组的第二个和最后一个元素相等,则发现循环引用。(1)
我们必须寻找内部循环引用并消除它们(否则我们将以堆栈溢出结束)。(2)
create or replace function find_cref(arr int[])
returns setof int[] language plpgsql
as $$
declare
vlen int = #arr;
vtarget int;
begin
if arr[2] = arr[vlen] then -- (1)
return query select arr;
else
if #uniq(sort(subarray(arr, 2)))+ 1 = vlen then -- (2)
for vtarget in
select target from the_table where source = arr[vlen]
loop
return query select find_cref (arr+ vtarget);
end loop;
end if;
end if;
end $$;
select c[1] id, subarray(c, 2) cref
from (
select find_cref(array[id, source, target]) c
from the_table) x
Run Code Online (Sandbox Code Playgroud)