2016-08-19 55 views
2

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

比方说,我有一个类型TPerson。 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 

这是我第一次使用这个REF事情。我甚至不确定我是否正确使用它。在我看来,这不是一个很好的方法('孩子'),但我没有选择。所以如果有人能解释我一个正确的方式来实现这一点,这将帮助我很多...

+0

这是句法上不正确的,你试图引用一个不存在的类型,并且在创建你引用的类型时不存在。你需要首先对其进行完整的定义。 – XING

回答

0

我不知道如果一个对象类型可以有一个相同类型的集合的成员必须是能够在收集之前在对象类型和对象类型之前定义集合。为了打破循环依赖一个需要引入一个间接层下面的方式(警告未测试的伪代码如下):

-- supertype 
create type object_t is object; 
create type object_list_t is table of ref object_t; 

-- subtype 
create type person_t under object_t (
name varchar2(20) 
,children object_list_t 
); 

然后在PERSON_T您使用treat的实施,从超亚型缩小。

另一个想法是把对象的关系放在一个特定的关系表中。看下面的例子。

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

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') 

refderef功能在Database Object-Relational Developer's Guide说明。如果您使用Oracle对象类型,那么这是一份您应该熟悉的文档。

+0

那么,这是一个很棒的答案!正如我所说的,这种方法对我来说是强加的,但由于它不起作用......我将把这种方法提交给我的经理。非常感谢 ! – Mastard

+0

@Mastard很高兴听到你发现有用的例子。但请注意性能。我从来没有使用过这个功能,所以我不知道选择参数会对性能产生什么影响(例如'where deref(parent).name ='Father'')。 – user272735