Не рекурсивно вызывать процедуру;вместо этого используйте один иерархический запрос:
Процедура :
CREATE PROCEDURE test_proc (
i_parent IN test_table.parent%TYPE,
o_children OUT type_test2
)
AS
BEGIN
SELECT CHILD
BULK COLLECT INTO o_children
FROM test_table
WHERE CHILD like '10-%'
START WITH parent = i_parent
CONNECT BY NOCYCLE
PRIOR child = parent
AND PRIOR child LIKE '11-%';
END;
/
Выполнение :
DECLARE
b type_test2:=type_test2();
BEGIN
test_proc( '50-100', b );
FOR i IN 1..b.COUNT LOOP
DBMS_OUTPUT.PUT_LINE( b(i) );
END LOOP;
END;
/
Вывод :
10-001
10-002
10-003
10-100
10-101
10-102
Альтернативный :
Вам даже не нужна процедура, и вы можете сделать все это за один раззапрос:
SELECT CHILD
FROM test_table
WHERE CHILD like '10-%'
START WITH parent = '50-100'
CONNECT BY NOCYCLE
PRIOR child = parent
AND PRIOR child LIKE '11-%';
Какие выходные данные:
| CHILD |
| :----- |
| 10-001 |
| 10-002 |
| 10-003 |
| 10-100 |
| 10-101 |
| 10-102 |
почему мы не получаем правильный вывод с помощью рекурсивной процедуры.
Каждый раз, когда вы используете BULK COLLECT INTO
, он повторно инициализирует коллекцию, в которую выводит, и перезаписывает предыдущие значения.Вам нужно BULK COLLECT INTO
другой коллекции, а затем объединить две, если вы хотите сохранить предыдущие значения.
Что-то вроде:
CREATE OR REPLACE PROCEDURE test_proc(
parent_data IN type_test2,
child_data OUT type_test2
)
AS
v_to_search type_test2;
v_search_results type_test2;
i PLS_INTEGER;
BEGIN
SELECT child
BULK COLLECT INTO child_data
FROM test_table
WHERE parent MEMBER OF parent_data
AND child LIKE '10-%';
SELECT child
BULK COLLECT INTO v_to_search
FROM test_table
WHERE parent MEMBER OF parent_data
AND child LIKE '11-%';
IF v_to_search.COUNT = 0 THEN
RETURN;
END IF;
test_proc( v_to_search, v_search_results );
i := child_data.COUNT;
child_data.EXTEND( v_search_results.COUNT );
FOR j IN 1 .. v_search_results.COUNT LOOP
child_data(i+j) := v_search_results(j);
END LOOP;
END;
/
Однако, это может застрять в бесконечностицикл, если в ваших данных есть цикл.Приведенный выше иерархический запрос обнаружит циклы и прекратит итерацию (или если вы удалите ключевое слово NOCYCLE
, возникнет исключение).
db <> fiddle здесь