Как создать объект включаюший объект этого же типа, есть ли поддержка рекурсивных объектов?
Пробую создать объект для строгого иерархического дерева, включающий в себя массив с тем же типом данных.
В Object-Relational Developer's Guide нашел ссылки на подчиненные/встроенные типы данных, которые отличаются друг от друга - например, department включает в себя address. В этом документе также есть раздел разрешения круговых ссылок, но опять же, между объектами разных типов. А надо создать объект включающий объект этого же типа:
create or replace type a_obj is object (myself varchar2(10), parent number, children number);
/
Type A_OBJ compiled
create or replace type c_obj is table of ref a_obj;
/
Type C_OBJ compiled
create or replace type a_obj force is object (
myself varchar2(10), parent a_obj, children c_obj);
/
Warning: Type created with compilation errors.
LINE/COL ERROR
--------- -------------------------------------------------------------
0/0 PL/SQL: Compilation unit analysis terminated
1/1 PLS-00318: type "A_OBJ" is malformed because
it is a non-REF mutually recursive type
Есть ли поддержка рекурсивного объявления объектов? Другими словами, как создать объект включаюший объект этого же типа?
Свободный перевод вопроса Does Oracle Database PL/SQL support recursive objects? от участника @tthomson001
Ответы (2 шт):
Сначало сделайте форвард декларацию типа данных (без аттрибутов), затем атрибуту parent задайте тип REF:
create or replace type a_obj
/
Type A_OBJ compiled
create or replace type c_obj is table of ref a_obj
/
Type C_OBJ compiled
create or replace type a_obj is object (
myself varchar2(10), parent ref a_obj, children c_obj)
/
Type A_OBJ compiled
Если нужно решение на чистом PL/SQL, то есть, нет таблицы с этим типом данных и ссылка через REF невозможна, то форвард декларация не будет работать:
create or replace type a_obj
/
Type created.
create or replace type c_obj is table of a_obj
/
Warning: Type created with compilation errors.
LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 PL/SQL: Compilation unit analysis terminated
1/24 PLS-00311: the declaration of "A_OBJ" is incomplete or malformed
Необходимо создать базвоый объект, и с ним создать атрибут со вложенной таблицей:
create or replace type baseobj force is object (myself varchar2 (10)) not instantiable not final
/
create or replace type nodetab is table of baseobj
/
create or replace type nodeobj under baseobj (children nodetab)
/
Пример использованя для иерархического дерева:
declare
root nodeobj;
procedure printout (n nodeobj, l int := 0) is
begin
dbms_output.put_line (lpad (' ', l*4)||n.myself||'->'||n.children.count||' nodes');
for i in 1..n.children.count loop
printout (treat (n.children(i) as nodeobj), l+1);
end loop;
end;
begin
root := nodeobj (
'root', nodetab (
nodeobj ('node1',
nodetab (nodeobj ('leaf11', nodetab ()), nodeobj ('leaf12', nodetab ()))),
nodeobj ('node2',
nodetab (nodeobj ('leaf21', nodetab ()), nodeobj ('leaf22', nodetab ())))));
printout (root);
end;
/
Результат:
root->2 nodes
node1->2 nodes
leaf11->0 nodes
leaf12->0 nodes
node2->2 nodes
leaf21->0 nodes
leaf22->0 nodes