目录
Oracle 复杂数据类型
用户自定义数据类型(User-defined Data Type)
oracle支持对象类型(Object Type)、嵌套类型(Nested Table Type)和可变数组类型(Varray Data Type)三种用户自定义数据类型。集合数据类型:
类似于编程语言中数组也就是。pl/sql集合类型包括关联数组Associative array(索引表 pl/sql table)、嵌套表(Nested Table)、变长数组(VARRAY)。
1. 对象类型
create or replace type type_name as object (
v_name1 datatype[,v_name2 datatype,...],
[member|static method1 spec,
member|static method2 spec,...]);
create or replace type body type_name as
member|static method1 body;
member|static method1 body;...
1.1 对象类型头
用于定义对象的公用属性和方法;
属性:最少要包含一个属性,最多包含1000个属性。定义时必须提供属性名和数据类型,但不能指定默认值和not null。并且不能包括long、long raw、rowid、urowid和PL/SQL特有类型(boolean\%type\%rowtype\ref curdor等);
可以包含也可以不包含方法,可以定义构造方法、member方法、static方法、map方法和order方法。
1.2 对象类型体
用于实现对象类型头所定义的公用方法。(如果对象类型头中没有方法,那么就不需要对象类型体);定义对象类型可以包含也可以不包含方法,可以定义构造方法、member方法、static方法、map方法和order方法。
1)、构造方法
用于初始化对象并返回对象实例。构造方法是与对象类型同名的函数,默认的构造方法参数是对象类型的所有属性。9i前只能使用系统默认的构造方法、9i后可自定义构造函数,自定义必须使用constructor function关键字
2)、member方法
用于访问对象实例的数据。当使用member方法时,可以使用内置参数self访问当前对象实例。
当定义member方法时,无论是否定义self参数,它都会被作为第一个参数传递给member方法。
但如果要定义参数self,那么其类型必须要使用当前对象类型。member方法只能由对象实例调用,而不能由对象类型调用。
3)、static方法
用于访问对象类型,可以在对象类型上执行全局操作,而不需要访问特定对象实例的数据,因此static方法引用self参数。static方法只能由对象类型调用,不能由对象实例调用(和member相反)。
4)、map方法
对象类型不同于标量类型可以直接比较,为了按照特定规则排序对象实例的数据,可以定义map方法,但只能有一个,与order互斥。map方法将对象实例映射成标量数值来比较。
5)、order方法
map可以在对多个对象实例之间排序,而order只能比较2个实例的大小。定义对象类型时最多只能定义一个order方法,而且map和order方法不能同时定义。使用原则是可不用则均不用,比较2个对象则用ordder,对个对象则用map。
2. 嵌套表类型
TYPE type_name IS TABLE OF element_type;
a. 下标从1开始,元素个数没有限制(*使用时必须先初始化,用extend属性可以扩展元素个数)
b. 可作为表定义数据类型,但是前提是要先create 创造嵌套表类型,这就可以实现1对多了定义 c. 和索引表的区别也就是看看有无index by语句,嵌套表的索引固定是int型的 .
type / create type 区别:
用 create 后面用 as , 若直接用 type 后面用is
create 是创 object , 而 type 是创record .
另 type用在语句块中,而create 是的独立的.
2.1 例子
SET SERVEROUTPUT ON SIZE 99999;
DECLARE
TYPE names_table IS TABLE OF VARCHAR2(10);
TYPE grades IS TABLE OF INTEGER;
names names_table;
marks grades;
total integer;
BEGIN
names := names_table('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz');
marks:= grades(98, 97, 78, 87, 92);
total := names.count;
dbms_output.put_line('Total '|| total || ' Students');
FOR i IN 1 .. total LOOP
dbms_output.put_line('Student:'||names(i)||', Marks:' || marks(i));
end loop;
END;
/
3. 可变数组类型
TYPE type_name IS VARRAY(size_limit) OF element_type[NOT NULL];
a. 这个就和java中的数组差不多了,下标from 1 ,定义时先指定最大元素个数,也和varchar2(size)这种一样。
b. 使用时也必须先用构造方法初始化 ,可以作为表列类型
3.1 例子
declare
type varr is VARRAY(10) of int;
v_varr varr :=varr();
begin
for i in 1..5 loop
v_varr.extend;
v_varr(i) :=i*i;
end loop;
for i in 1..5 loop
dbms_output.put_line(v_varr(i));
end loop;
end;
/
4. 索引类型(关联数组)
TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY key_type;
type_name:用户自定义数据类型的名字
element_type:索引表中元素类型
key_type:索引表元素下标的数据类型(BINARY_INTEGERPLS_INTEGER,VARCHAR2)
a. 下标无限制,可以为负数
b. 元素个数无限制
4.1 例子
declare
type index_tab_type is table of varchar2(30) index by BINARY_INTEGER;
v_table index_tab_type;
begin
v_table(-1) :='hello';--设定下标为-1的元素的值
v_table(1) :=',';
dbms_output.put_line(v_table(-1)||'-'||v_table(1));
dbms_output.put_line('元素个数:'||v_table.count);
v_table(5) :='world';
dbms_output.put_line('元素个数:'||v_table.count);
dbms_output.put_line('第一个元素'||v_table.first);
dbms_output.put_line('最后一个元素'||v_table.last);
end;
/
运行结果:
hello-,
元素个数:2
元素个数:3
第一个元素-1
最后一个元素5
PL/SQL 过程已成功完成。
5. 记录类型
TYPE RECORD_NAME IS RECORD(
V1 DATA_TYPE1 [NOT NULL][:=DEFAULT_VALUE],
V2 DATA_TYPE2 [NOT NULL][:=DEFAULT_VALUE],
VN DATA_TYPEN [NOT NULL][:=DEFAULT_VALUE]
);
5.1 例子
SET SERVEROUTPUT ON SIZE 99999;
DECLARE
type books is record
(title varchar(50),
author varchar(50),
subject varchar(100),
book_id number);
book1 books;
book2 books;
BEGIN
-- Book 1 specification
book1.title := 'C Programming';
book1.author := 'TanHao';
book1.subject := 'C Programming Tutorial';
book1.book_id := 1920122;
-- Book 2 specification
book2.title := 'Telecom Billing';
book2.author := 'LiDawei';
book2.subject := 'Telecom Billing Tutorial';
book2.book_id := 2032942;
-- Print book 1 record
dbms_output.put_line('Book 1 title : '|| book1.title);
dbms_output.put_line('Book 1 author : '|| book1.author);
dbms_output.put_line('Book 1 subject : '|| book1.subject);
dbms_output.put_line('Book 1 book_id : ' || book1.book_id);
-- Print book 2 record
dbms_output.put_line('Book 2 title : '|| book2.title);
dbms_output.put_line('Book 2 author : '|| book2.author);
dbms_output.put_line('Book 2 subject : '|| book2.subject);
dbms_output.put_line('Book 2 book_id : '|| book2.book_id);
END;
/
6. 集合属性和方法
集合属性是数据库提供给用户的操作集合的方法(函数和过程),
过程包括:extend,trim,delete
函数包括:exists,count,limit,first,last,prior,next。
集合方法只能在pl/sql语句中使用,不能在sql语句中使用。
6.1 集合的方法
exists(index) 索引处的元素是否存在
count 当前集合中的元素总个数
limit 集合元素索引的最大值
索引表和嵌套表是不限个数的,所以返回null,变长数组返回定义时的最大索引
first 返回集合第一个元素索引
last 返回集合最后一个元素索引
prior 当前元素的前一个
next 当前元素的后一个
extend 扩展集合的容量,增加元素 只是用于嵌套表和varry类型
x.extend 增加一个null元素
x.extend(n) 增加n个null元素
x.extend(n,i) 增加n个元素,元素值与第i个元素相同
trim 从集合的尾部删除元素 只用于嵌套表和varry类型
trim 从集合尾部删除一个元素
trim(n) 从集合尾部删除n个元素
delete 按索引删除集合元素 只适用于嵌套表,delete(n)\delete(m,n)不适用于varray。
delete 删除所有
delete(index) 删除第index个
delete(a,b) 删除a--b之间的所有元素
处理单行单列数据,可以使用标量变量(varchar2、number、date、boolean);
处理单行多列的数据,可以使用pl/sql记录(%rowtype,record);
处理单列多行数据,可以使用pl/sql集合(table、varray);
那么处理多列多行数据,可以集合类型的嵌套;
6.2 集合特征
6.3 集合类型的嵌套(联合)
1.table和%rowtype的联合
declare
type type_tab_ename is table of emp%rowtype;
v_arr type_tab_ename:=type_tab_ename();
v_cnt number:=1;
begin
for rs in (select * from emp) loop
v_arr.extend;
v_arr(v_cnt):=rs;
dbms_output.put_line('雇员名:'||v_arr(v_cnt).ename);
v_cnt:=v_cnt+1;
end loop;
end;
2.二维数组 varray和varray的嵌套
declare
type d1_varray_type is varray(10) of number;--定义一维VARRAY
type nd1_varray_type is varray(5) of d1_varray_type;--定义二维VARRAY集合
--初始化二维集合变量
v_arr nd1_varray_type:=nd1_varray_type(
d1_varray_type(2,4),
d1_varray_type(5,73));
begin
dbms_output.put_line('显示二维数组所有元素');
for i in 1..v_arr.count loop
for j in 1..v_arr(i).count loop
dbms_output.put_line('v_arr('||i||','||j||')='||v_arr(i)(j));
end loop;
end loop;
end;
(2,4)
(5,73)
如果多维集合的元素个数没有限制,那么可以在嵌套表类型中嵌套另一个嵌套表类型
3.二维嵌套表 table和table的嵌套
declare
type d1_table_type is table of number;--定义一维嵌套表
type nd1_table_type is table of d1_table_type;--定义二维嵌套表集合
--初始化二维集合变量
v_tab nd1_table_type:=nd1_table_type(
d1_table_type(58,100,102),
d1_table_type(55,6),
d1_table_type(2));
begin
dbms_output.put_line('显示二维数组所有元素');
for i in 1..v_tab.count loop
for j in 1..v_tab(i).count loop
dbms_output.put_line('v_tab('||i||','||j||')='||v_tab(i)(j));
end loop;
end loop;
end;