使用具有超类型属性的类型创建对象表

时间:2016-04-19 15:31:13

标签: oracle

我正在尝试创建一个oracle-object类型的oracle表。

以下是我的对象结构的样子

CREATE OR REPLACE TYPE PERS_T AS OBJECT 
( 

 empno number(4)
, ename varchar2(10)
, job varchar2(9)
, hiredate DATE
, sal number(7,2)
, comm number(7,2)
, deptno number(2)
)NOT FINAL;

CREATE OR REPLACE TYPE EMP_T FORCE UNDER pers_t (
  mgr pers_t
);

所有这些都很好,但当我尝试使用

创建EMP_T类型的表格时
CREATE TABLE table_name(emp_type EMP_T);

我收到错误

SQL Error: ORA-30756: cannot create column or table of type that contains a supertype attribute

在oracle中可以创建这样的表吗?

2 个答案:

答案 0 :(得分:2)

我不这么认为。根据Oracle自己的支持数据库,以下内容适用于ora-30756

  

ORA-30756的消息文件中的错误文本,原因和操作

     

版本9.2,10.1,10.2,11.1,11.2,12.1

     

错误:ORA-30756无法创建包含超类型属性的列或表类型

     

原因:用户尝试创建对象类型的列或表     包含超类型属性。这是不受支持的,因为它会导致     在我们当前的存储模型中进行无限递归。注意创建     一个类型的列意味着我们创建了对应于all的列     子类型属性也是如此。   操作:更改类型定义以包含超类型REF属性     而不是超类型对象属性。

你已经创建了一个超级类型的PERS_T,所以我相信这是你的问题。正如文章所述,您可以创建引用属性而不是对象属性作为解决方法,如@tbone所解释的那样 - CREATE TABLE table_name(emp_type REF EMP_T);

答案 1 :(得分:0)

您不允许使用UNDER关键字同时使用相同类型的 HAS-A 关系来键入 IS-A 关系。这最终转化为创建一个引用自身的对象,它将导致无限递归。您可以使用 REF 在代码中指向相同类型的对象,如下所示:

CREATE OR REPLACE TYPE EMP_T UNDER PERS_T (
  mgr REF PERS_T
);

create table table_name(emp_type emp_t);
desc table_name;
Name     Null Type    
-------- ---- ------- 
EMP_TYPE      EMP_T() 

Oracle类型继承中的IS-A和HAS-A关系

IS-A和HAS-A关系都可以实现代码的多态性和可重用性,但它们定义了两种类型之间根本不同的关系。

<强> IS-A

UNDER关键字用于使用IS-A继承模型子类型关系。例如,employee IS-A person使用以下内容定义emp_id

create type person_type as object(ssn number, address varchar2(100)) NOT FINAL;

-- Employee is a **person** with an emp_id.
create type employee_type under person_type(emp_id number)

我们的想法是employee_type的对象也是person_type的对象,但附加了emp_id的规范。这允许通过扩展person_type超类型来启用代码重用,从而实现多态的继承模型。请注意,始终可以定义person_type student的另一个扩展名,如下所示:

-- Student is a person with a student_id
create type student_type under person_type(student_id number)

<强> HAS-A

因此,Oracle在尝试创建复合子类型时不会强制使用任何关键字。从其他本机类型中自由定义包含一个或多个超类型的子类型在语法上不合适。例如,定义复合子类型classroom_type是合法的,方法是将其与teacher类型为person,3个类型person的学生以及number类型的房间号码,例如:

create type classroom_type as object ( teacher person_type, 
                                   student1 person_type, 
                                   student2 person_type, 
                                   student3 person_type, 
                                   room_number number)

当一个对象属于另一个对象时,两个对象之间存在HAS-A关系,即前一个对象由后者组成。

但是,当您将数据从一个地方复制到另一个地方时,这种做法可能会导致不必要的大型对象复制。为了使事情更有效,类似于passing by reference in programming的概念,REF修饰符允许您传递指向对象的指针,以便在包括复合子类型在内的各种场景中使用。因此,class_type的上述DDL可以重写为:

create type class_type as object ( teacher ref person_type, 
                                   student1 ref person_type, 
                                   student2 ref person_type, 
                                   student3 ref person_type, 
                                   room_number number)

并且效率更高。值得注意的是,对引用对象的更改将自动传播到下游。

在问题的例子中,OP希望同时使用IS-A关系以及HAS-A关系,例如

An employee "is a" person "has a" manager (who "is a" person)

这是对现实世界概念的公平翻译。但是,为了使其合法而不导致无限递归,我们将其修改为:

An employee "is a" person "has a" manager (who "is a" 'reference to' a person)