在存储过程中递归调用 TreeRelation 引发游标错误 'already in use'

Recursive call of TreeRelation in stored procedure raises cursor error 'already in use'

我在 postgres 中创建了一个简单的树关系。父节点可以有 n 个节点。为了从父节点获取所有子节点,我想编写一个递归调用自身的存储过程。这就是我卡住的地方。

我的想法是我用父节点调用过程,然后我得到它的所有子节点,再次为每个子节点调用该过程。递归的步骤,方法的调用,好像把程序杀了,但我说不出为什么。

代码:

CREATE OR REPLACE PROCEDURE treeDown(INTEGER)
LANGUAGE plpgsql
AS $$
DECLARE
    cur_childs CURSOR FOR select * from TreeRelation where von =  AND from < to;
    rec RECORD;
BEGIN
    FOR rec IN cur_childs LOOP
        CALL treeDown(rec.to); -- seems to die here
        RAISE NOTICE '% is a child from %', rec.to, ;
    end loop;
END;
$$;

错误信息:

[42P03] ERROR: cursor "cur_childs" already in use Wobei: PL/pgSQL function treedown(integer) line 6 at FOR over cursor SQL statement "CALL treeDown(rec.nach)" PL/pgSQL function treedown(integer) line 7 at CALL

有什么想法吗?我是在正确执行调用还是在存储过程中调用存储过程的不同方法。

您可以使用匿名游标代替命名游标,因此无需重复使用已经存在的游标。

...
FOR rec IN (SELECT *
                   FROM treerelation
                   WHERE ...) LOOP
...

我还找到了使用 WITH RECURSIVE 的工作方式:

-- 3 is our start node in this case
WITH RECURSIVE test(s) AS (
            select to from TreeRelation where from = 3 AND from < to
        UNION
            select to from test, TreeRelation where from = test.s AND from < to
        ) select * from test;

我学到了什么? WITH RECURSIVE 总是有 1 non-recursive select1 recursive select。递归 select 能够访问我们的临时 table test 中的数据,该临时 table test 由我们的 non-recursive select 填充。每个条目 test 都会调用递归函数(第二个 select),每个条目都来自 non-recursive select(第一个)。