在 PostgreSQL 表中查找循环引用?

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

我想找到这样的例子。谁能建议我如何进行此操作。

kli*_*lin 1

这可以通过下面的递归函数来完成。该函数使用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)