Рекурсивный вызов TreeRelation в хранимой процедуре вызывает ошибку курсора «уже используется» - PullRequest
0 голосов
/ 22 мая 2019

Я создал простое древовидное отношение в postgres.У родительского узла может быть n-узлов.Чтобы получить все дочерние элементы от родительского узла, я хочу написать хранимую процедуру, которая вызывает себя рекурсивно.Это та точка, в которой я застрял.

Моя идея состояла в том, чтобы я вызывал процедуру с отцовским узлом, затем я получал все его дочерние элементы и снова вызывал процедуру для каждого дочернего элемента.Рекурсивный шаг, вызов метода, кажется, убивает процедуру, но я не могу сказать, почему.

Код:

CREATE OR REPLACE PROCEDURE treeDown(INTEGER)
LANGUAGE plpgsql
AS $$
DECLARE
    cur_childs CURSOR FOR select * from TreeRelation where von = $1 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, $1;
    end loop;
END;
$$;

Сообщение об ошибке:

[42P03] ОШИБКА: курсор «cur_childs» уже используется Wobei: строка 6 изменения функции PL / pgSQL (целое число) строка 6 в FOR по отношению к курсору SQL-оператор «CALL treeDown (rec.nach)» строка изменения функции PL / pgSQL (целое число)7 at CALL

Есть идеи?Я правильно выполняю вызов или есть другой способ вызова хранимой процедуры в хранимой процедуре.

Ответы [ 2 ]

1 голос
/ 22 мая 2019

Вместо именованного курсора вы можете использовать анонимный курсор, поэтому нет необходимости повторно использовать уже существующий.

...
FOR rec IN (SELECT *
                   FROM treerelation
                   WHERE ...) LOOP
...
0 голосов
/ 23 мая 2019

Я также нашел рабочий способ, используя 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. Рекурсивный выбор может получить доступ к данным из нашей временной таблицы test, которая заполняется нашим нерекурсивным выбором. Рекурсивная функция (2-й выбор) вызывается для каждой записи test, получаемой из нерекурсивного выбора (1-й выбор).

...