2016-08-19 90 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