定义新的用户定义类型,可以是对象类型、集合类型(嵌套表类型或 varray 类型)或复合类型。
语法
对象类型
CREATE [ OR REPLACE ] TYPE name
[ AUTHID { DEFINER | CURRENT_USER } ]
{ IS | AS } OBJECT
( { attribute { datatype | objtype | collecttype } }
[, ...]
[ method_spec ] [, ...]
) [ [ NOT ] { FINAL | INSTANTIABLE } ] ...
其中 method_spec
是:
[ [ NOT ] { FINAL | INSTANTIABLE } ] ...
[ OVERRIDING ]
subprogram_spec
subprogram_spec
是:
{ MEMBER | STATIC }
{ PROCEDURE proc_name
[ ( [ SELF [ IN | IN OUT ] name ]
[, argname [ IN | IN OUT | OUT ] argtype
[ DEFAULT value ]
] ...)
]
|
FUNCTION func_name
[ ( [ SELF [ IN | IN OUT ] name ]
[, argname [ IN | IN OUT | OUT ] argtype
[ DEFAULT value ]
] ...)
]
RETURN rettype
}
嵌套表类型
CREATE [ OR REPLACE ] TYPE name { IS | AS } TABLE OF
{ datatype | objtype | collecttype }
varray 类型
CREATE [ OR REPLACE ] TYPE name { IS | AS }
{ VARRAY | VARYING ARRAY } (maxsize) OF { datatype | objtype }
复合类型
CREATE [ OR REPLACE ] TYPE name { IS | AS }
( [ attribute datatype ][, ...]
)
说明
CREATE TYPE定义新的用户定义数据类型。可以创建的类型包括对象类型、嵌套表类型、varray类型或复合类型。嵌套表类型和varray类型属于称为集合的类型类别。
复合类型与Oracle数据库不兼容。不过,复合类型可以通过SPL程序进行访问,与本节中所述的其他类型一样。
在CREATE TYPE命令中,如果包括Schema名称,则在指定的Schema中创建类型,否则在当前Schema中创建类型。新类型的名称不得与同一Schema中的任何现有类型匹配,除非旨在更新现有类型的定义,在此情况下使用CREATE OR REPLACE TYPE。
- OR REPLACE选项当前不能用于添加、删除或修改现有对象类型的属性。可使用DROP TYPE命令首先删除现有对象类型。OR REPLACE选项可用于添加、删除或修改现有对象类型中的方法。
- ALTER TYPE ALTER ATTRIBUTE命令的PostgreSQL形式可用于更改现有对象类型中属性的数据类型。ALTER TYPE命令不能添加或删除对象类型中的属性。
创建类型的用户成为该类型的所有者。
参数
参数 | 说明 |
---|---|
name | 要创建的类型的名称(可能是Schema限定的)。 |
DEFINER | CURRENT_USER | 指定是采用对象类型所有者(DEFINER)的特权,还是采用执行对象类型中方法的当前用户(CURRENT_USER)的特权,来确定是否允许访问对象类型中引用的数据库对象。默认值为DEFINER。 |
attribute | 对象类型或复合类型中属性的名称。 |
datatype | 定义对象类型或复合类型属性,或正在创建的集合类型元素的数据类型。 |
objtype | 定义对象类型属性或正在创建的集合类型元素的对象类型的名称。 |
collecttype | 定义对象类型属性或正在创建的集合类型元素的集合类型的名称。 |
FINAL | NOT FINAL |
|
INSTANTIABLENOT |INSTANTIABLE |
|
OVERRIDING | 如果指定OVERRIDING,则method_spec使用相同数量的同名方法参数覆盖同名方法,这些参数具有与超类型中的定义相同的数据类型、相同的顺序以及相同的返回类型(如果方法为函数)。 |
MEMBER | STATIC | 如果子程序在对象实例上运行,请指定MEMBER。如果子程序的运行独立于任何特定对象实例,请指定STATIC。 |
proc_name | 要创建的存储过程的名称。 |
SELF [ IN | IN OUT ] name | 对于成员方法,存在一个名为SELF的隐式内置参数,其数据类型就是正在定义的对象类型的数据类型。SELF引用当前正在调用方法的对象实例。SELF可以在参数列表中显式声明为IN或IN OUT参数。如果显式声明,则SELF必须为参数列表中的第一个参数。如果未明确声明SELF,则其参数模式默认为IN OUT(对于成员存储过程)和IN(对于成员函数)。 |
argname | 参数的名称。参数在方法主体中通过该名称进行引用。 |
argtype | 方法参数的数据类型。参数类型可以是基本数据类型或用户定义类型,如嵌套表或对象类型。任何基本类型不得指定长度,例如,指定VARCHAR2,而不是VARCHAR2(10)。 |
DEFAULT value | 如果方法调用中未提供默认值,则为输入参数提供一个默认值。对于模式为IN OUT或OUT的参数,可能无法指定DEFAULT。 |
func_name | 要创建的函数的名称。 |
rettype | 返回数据类型,可以是为argtype列出的任意类型。对于argtype,不得为rettype指定长度。 |
maxsize | varray中允许的最大元素数量。 |
示例
- 创建对象类型
创建对象类型addr_obj_typ。
CREATE OR REPLACE TYPE addr_obj_typ AS OBJECT ( street VARCHAR2(30), city VARCHAR2(20), state CHAR(2), zip NUMBER(5) );
创建包含成员方法display_emp的对象类型emp_obj_typ。
CREATE OR REPLACE TYPE emp_obj_typ AS OBJECT ( empno NUMBER(4), ename VARCHAR2(20), addr ADDR_OBJ_TYP, MEMBER PROCEDURE display_emp (SELF IN OUT emp_obj_typ) );
创建包含静态方法get_dname的对象类型dept_obj_typ。
CREATE OR REPLACE TYPE dept_obj_typ AS OBJECT ( deptno NUMBER(2), STATIC FUNCTION get_dname (p_deptno IN NUMBER) RETURN VARCHAR2, MEMBER PROCEDURE display_dept );
- 创建集合类型
创建数据类型NUMBER(8,2)的嵌套表类型budget_tbl_typ。
CREATE OR REPLACE TYPE budget_tbl_typ IS TABLE OF NUMBER(8,2);
- 创建并使用复合类型
以下示例显示了从匿名块访问复合类型的用法。
复合类型的创建方法如下:
CREATE OR REPLACE TYPE emphist_typ AS ( empno NUMBER(4), ename VARCHAR2(10), hiredate DATE, job VARCHAR2(9), sal NUMBER(7,2) );
以下是访问复合类型的匿名块:
DECLARE v_emphist EMPHIST_TYP; BEGIN v_emphist.empno := 9001; v_emphist.ename := 'SMITH'; v_emphist.hiredate := '01-AUG-17'; v_emphist.job := 'SALESMAN'; v_emphist.sal := 8000.00; DBMS_OUTPUT.PUT_LINE(' EMPNO: ' || v_emphist.empno); DBMS_OUTPUT.PUT_LINE(' ENAME: ' || v_emphist.ename); DBMS_OUTPUT.PUT_LINE('HIREDATE: ' || v_emphist.hiredate); DBMS_OUTPUT.PUT_LINE(' JOB: ' || v_emphist.job); DBMS_OUTPUT.PUT_LINE(' SAL: ' || v_emphist.sal); END; EMPNO: 9001 ENAME: SMITH HIREDATE: 01-AUG-17 00:00:00 JOB: SALESMAN SAL: 8000.00
以下示例显示了从在程序包主体内声明的用户定义记录类型访问复合类型的用法。
复合类型的创建方法如下:
CREATE OR REPLACE TYPE salhist_typ AS ( startdate DATE, job VARCHAR2(9), sal NUMBER(7,2) );
程序包规格的定义方法如下:
CREATE OR REPLACE PACKAGE emp_salhist IS PROCEDURE fetch_emp ( p_empno IN NUMBER ); END;
程序包主体的定义方法如下:
CREATE OR REPLACE PACKAGE BODY emp_salhist IS TYPE emprec_typ IS RECORD ( empno NUMBER(4), ename VARCHAR(10), salhist SALHIST_TYP ); TYPE emp_arr_typ IS TABLE OF emprec_typ INDEX BY BINARY_INTEGER; emp_arr emp_arr_typ; PROCEDURE fetch_emp ( p_empno IN NUMBER ) IS CURSOR emp_cur IS SELECT e.empno, e.ename, h.startdate, h.job, h.sal FROM emp e, jobhist h WHERE e.empno = p_empno AND e.empno = h.empno; i INTEGER := 0; BEGIN DBMS_OUTPUT.PUT_LINE('EMPNO ENAME STARTDATE JOB ' || 'SAL '); DBMS_OUTPUT.PUT_LINE('----- ------- --------- --------- ' || '---------'); FOR r_emp IN emp_cur LOOP i := i + 1; emp_arr(i) := (r_emp.empno, r_emp.ename, (r_emp.startdate, r_emp.job, r_emp.sal)); END LOOP; FOR i IN 1 .. emp_arr.COUNT LOOP DBMS_OUTPUT.PUT_LINE(emp_arr(i).empno || ' ' || RPAD(emp_arr(i).ename,8) || ' ' || TO_CHAR(emp_arr(i).salhist.startdate,'DD-MON-YY') || ' ' || RPAD(emp_arr(i).salhist.job,10) || ' ' || TO_CHAR(emp_arr(i).salhist.sal,'99,999.99')); END LOOP; END; END;
请注意,在程序包主体内TYPE emprec_typ IS RECORD数据结构的声明中,salhist字段采用CREATE TYPE salhist_typ语句所创建的SALHIST_TYP复合类型定义。
关联的数组定义TYPE emp_arr_typ IS TABLE OF emprec_typ引用记录类型数据结构emprec_typ,其中包含的字段salhist采用SALHIST_TYP复合类型定义。
以下显示了程序包存储过程的调用,从emp和jobhist表联合加载数组,然后显示数组内容:
EXEC emp_salhist.fetch_emp(7788); EMPNO ENAME STARTDATE JOB SAL ----- ------- --------- --------- --------- 7788 SCOTT 19-APR-87 CLERK 1,000.00 7788 SCOTT 13-APR-88 CLERK 1,040.00 7788 SCOTT 05-MAY-90 ANALYST 3,000.00 polar-spl Procedure successfully completed