包含相同对象列表的Oracle对象

包含相同对象列表的Oracle对象,oracle,plsql,Oracle,Plsql,我目前正在努力解决PL/SQL问题,但我还没有找到一个明确的答案。问题是,我有一个类型为T的对象,它可以包含一个相同类型为T的对象列表 假设我有一个T型人。TPerson由一个名称和一系列子项定义。我有一个祖父,他的两个儿子,第一个有两个女儿 在PL/SQL中,经过一些研究,我做了以下工作: CREATE OR REPLACE TYPE TPerson IS OBJECT ( Name VARCHAR2(30), Children

我目前正在努力解决PL/SQL问题,但我还没有找到一个明确的答案。问题是,我有一个类型为T的对象,它可以包含一个相同类型为T的对象列表

假设我有一个T型人。TPerson由一个名称和一系列子项定义。我有一个祖父,他的两个儿子,第一个有两个女儿

在PL/SQL中,经过一些研究,我做了以下工作:

CREATE OR REPLACE TYPE TPerson IS OBJECT 
    (
     Name             VARCHAR2(30),
     Children         REF TPersonList,
     constructor function TPerson(name VARCHAR2) return self as result
    );

CREATE OR REPLACE TYPE body TPerson as
   constructor function TPerson(aname VARCHAR2) return self as result is
       begin
           Name       := aname;
           Children   := TPersonList();
           return;
       end;
   end;

CREATE OR REPLACE TYPE TPersonList IS TABLE OF REF TPerson';
一切正常。但是TPerson类型没有正确编译,我有一个编译错误:

pls-00532 target of ref must be a complete or incomplete object type

这是我第一次用这个东西。我甚至不确定我是否正确使用了它。在我看来,这不是一个很好的方式(孩子的事情),但我没有选择。因此,如果有人能向我解释一种实现这一点的正确方法,那将对我有很大帮助……

我不确定一个对象类型是否可以拥有与一个对象类型相同的集合成员,因为一个人必须能够在对象类型之前定义集合,在集合之前定义对象类型。要打破循环依赖关系,需要以以下方式引入一个间接级别(下面是警告未测试的伪代码):

然后在person\t的实现中,您使用它来缩小从超类型到子类型的范围

另一个想法是在特定的关系表中拥有对象的关系。请参见下面的示例

首先创建一个简单的人员类型:

create type person_t is object (
 name varchar2(20)
);
/
show errors

create table persons of person_t;

insert into persons values(person_t('Grandfather'));
insert into persons values(person_t('Father'));
insert into persons values(person_t('Mother'));
insert into persons values(person_t('Son 1'));
insert into persons values(person_t('Daughter 1'));
insert into persons values(person_t('Son 2'));
其次,为父子关系创建一个表:

create table x (
 parent ref person_t
,child ref person_t
);

-- build a family tree
insert into x values(
 (select ref(p) from persons p where name = 'Grandfather')
,(select ref(p) from persons p where name = 'Father')
);

insert into x values(
 (select ref(p) from persons p where name = 'Father')
,(select ref(p) from persons p where name = 'Son 1')
);

insert into x values(
 (select ref(p) from persons p where name = 'Father')
,(select ref(p) from persons p where name = 'Son 2')
);

insert into x values(
 (select ref(p) from persons p where name = 'Father')
,(select ref(p) from persons p where name = 'Daughter 1')
);

insert into x values(
 (select ref(p) from persons p where name = 'Mother')
,(select ref(p) from persons p where name = 'Son 1')
);

insert into x values(
 (select ref(p) from persons p where name = 'Mother')
,(select ref(p) from persons p where name = 'Son 2')
);

insert into x values(
 (select ref(p) from persons p where name = 'Mother')
,(select ref(p) from persons p where name = 'Daughter 1')
);
现在,您可以使用一个好的旧SQL遍历族树

column parent format a30
column child format a30

select deref(child) as child from x where deref(parent).name = 'Father';

CHILD(NAME)
------------------------------
PERSON_T('Son 1')
PERSON_T('Son 2')
PERSON_T('Daughter 1')

select deref(parent) as parent, deref(child) as child
from x
start with deref(parent).name = 'Grandfather'
connect by prior child = parent
;

PARENT(NAME)                   CHILD(NAME)
------------------------------ ------------------------------
PERSON_T('Grandfather')        PERSON_T('Father')
PERSON_T('Father')             PERSON_T('Son 1')
PERSON_T('Father')             PERSON_T('Son 2')
PERSON_T('Father')             PERSON_T('Daughter 1')

中介绍了
ref
deref
功能。如果您使用的是Oracle对象类型,您应该熟悉该文档。

这在语法上是不正确的,您试图引用的类型不存在,而创建类型时引用的对象不存在。首先,你需要对一做一个完整的定义。好吧,这是一个很棒的答案!正如我所说,这种方法是强加给我的,但由于它不起作用。。。我会将此方法提交给我的经理。非常感谢@很高兴听到你发现这个例子很有用。但是,请注意性能。我从未使用过此功能,因此我不知道选择引用会对性能产生什么影响(例如,在
中,其中deref(parent).name='Father'
)。
column parent format a30
column child format a30

select deref(child) as child from x where deref(parent).name = 'Father';

CHILD(NAME)
------------------------------
PERSON_T('Son 1')
PERSON_T('Son 2')
PERSON_T('Daughter 1')

select deref(parent) as parent, deref(child) as child
from x
start with deref(parent).name = 'Grandfather'
connect by prior child = parent
;

PARENT(NAME)                   CHILD(NAME)
------------------------------ ------------------------------
PERSON_T('Grandfather')        PERSON_T('Father')
PERSON_T('Father')             PERSON_T('Son 1')
PERSON_T('Father')             PERSON_T('Son 2')
PERSON_T('Father')             PERSON_T('Daughter 1')