在存储过程中递归调用 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 select
和 1 recursive select
。递归 select 能够访问我们的临时 table test
中的数据,该临时 table test
由我们的 non-recursive select 填充。每个条目 test
都会调用递归函数(第二个 select),每个条目都来自 non-recursive select(第一个)。
我在 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 select
和 1 recursive select
。递归 select 能够访问我们的临时 table test
中的数据,该临时 table test
由我们的 non-recursive select 填充。每个条目 test
都会调用递归函数(第二个 select),每个条目都来自 non-recursive select(第一个)。