ORACLE中自定义数据类型的方式一般是三种:RECORD、VARRAY、TABLE
RECORD
定义记录数据类型。它类似于JAVA语言中的对象,PL/SQL提供了将几个相关的、分离的、基本数据类型的变量组成一个整体的方法,即RECORD复合数据类型。在使用记录数据类型变量时,需要在声明部分先定义记录的组成、记录的变量,然后在执行部分引用该记录变量本身或其中的成员。
定义记录型数据类型的语法:
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]);
定义记录型数据类型实例:
declare
type typeOfRecord is record( -- 使用RECORD方式创建一个自定义数据类型
v_name testKD.Username%type,-- 自定义类型中的变量
v_curtime testKD.Curtime%type
);
v_record typeOfRecord;-- 在pl/sql程序中声明自定义类型
begin
-- 查询数据并设置到自定义类型中
select username,curtime into v_record from testKD where serviceno = '2017112800015';
dbms_output.put_line('name : ' || v_record.v_name);
dbms_output.put_line('curtime : ' || v_record.v_curtime);
end;
执行结果如下:
注意事项:record方式不能接受查出来是有多个值的。如,将where条件取消,将会报如下错误:
a.jpg
VARRAY
定义数组类型。数组是具有相同数据类型的一组成员的集合。每个成员都有一个唯一的下标,它取决于成员在数组中的位置。在PL/SQL中,数组数据类型是VARRAY(variable array,即可变数组)。
定义VARRAY数据类型的语法:
TYPE VARRAY_NAMEIS IS VARRAY(SIZE) OF ELEMENT_TYPE [NOT NULL];
其中,varray_name是VARRAY数据类型的名称,size是正整数,表示可以容纳的成员的最大数量,
每个成员的数据类型是element_typeo默认时,成员可以取空值,否则需要使用NOT NULL加以限制。
定义VARRAY数据类型实例:
declare
-- 自定义一个数组类型,数组的长度是5,
-- 数组中元素的类型是varchar2且取值范围是25
type typeOfVarray is varray(5) of varchar2(25);
v_varray typeOfVarray; -- 声明自定义数组变量
begin
-- 给自定义数组变量赋值
v_varray := typeOfVarray('1','2','3','4','5');
-- 注意:该VARRAY数组类型下标从1开始,而不是从0开始
dbms_output.put_line(v_varray(1));
dbms_output.put_line(v_varray(2));
dbms_output.put_line(v_varray(3));
dbms_output.put_line(v_varray(4));
dbms_output.put_line(v_varray(5));
end;
TABLE
定义记录表(或索引表)数据类型。它与记录类型相似,但它是对记录类型的扩展。它可以处理多行记录,类似于C语言中的二维数组,使得可以在PL/SQL中模仿数据库中的表。
定义TABLE类型语法:
TYPE TABLE NAME IS TABLE OF ELEMENT_TYPE [NOT NULL]
INDEX BY [BINARY_INTEGER|PLS_INTEGER|VARRAY2];
关键字INDEX BY表示创建一个主键索引,以便引用记录表变量中的特定行。
BINARY_INTEGER的说明:如语句,TYPE NUMBERS IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;其作用是,加了”INDEX BY BINARY_INTEGER ”后,NUMBERS类型的下标就是自增长,NUMBERS类型在插入元素时,不需要初始化,不需要每次EXTEND增加一个空间。而如果没有这句话“INDEX BY BINARY_INTEGER”,那就得要显示对初始化,且每插入一个元素到NUMBERS类型的TABLE中时,都需要先EXTEND。
定义TABLE类型实例1--存储单列多行:
-- 这个和VARRAY类似。但是赋值方式稍微有点不同,
-- 不能使用同名的构造函数进行赋值。如下:
declare
-- 自定义类型
type typeOfTable is table of varchar2(25) index by binary_integer;
v_table typeOfTable;-- 声明变量
begin
v_table(1) := '1';
v_table(2) := '2';
v_table(3) := '3';
v_table(4) := '4';
v_table(5) := '5';
-- 可见这种类型是支持任意个类型为varchar2的元素,
-- 也可以说它是一个可变长度的数组
dbms_output.put_line(v_tablle(1));
dbms_output.put_line(v_tablle(2));
dbms_output.put_line(v_tablle(3));
dbms_output.put_line(v_tablle(4));
dbms_output.put_line(v_tablle(5));
end;
定义TABLE类型实例1--存储多列多行和ROWTYPE结合使用:
-- 采用bulk collect可以将查询结果一次性加载到collections中。
-- 而不是通过cursor一条一条地处理
declare
-- 自定义一个table类型,
-- 这里就相当于创建了一个跟testkd表结构一样的多个临时表“容器”
type t_type is table of testkd%rowtype;
v_type t_type;-- 声明变量
begin
-- 查询并给v_type赋值
select testkd.id,testkd.name,testkd.flag bulk collect into v_type
from testkd
where testkd.id <= 5;
/*while v_type.count > 5 --此处不能使用count,是无效的
loop
dbms_output.put_line('id : ' || v_type.id
|| ' name : ' || v_type.name
|| ' flag : ' || v_type.flag);
--而且这种循环会报错:说id等属性没有声明
-- 从下面的测试中也可以看出,
-- 这种循环根本无法获取到数组的下标,
-- 而v_type本身可以看做是一个数组确实没有其他的属性,
-- 只是它里面的元素可以看做是个表结构,所以通过.xxx来获取值
end loop; */
dbms_output.put_line('id : ' || v_type(2).id
|| ' name : ' || v_type(2).name
|| ' flag : ' || v_type(2).flag);
dbms_output.put_line('--------------------------------');
for i in v_type.first .. v_type.last -- 这里留意一下first last的用法
loop
dbms_output.put_line('id : ' || v_type(i).id
|| ' name : ' || v_type(i).name
|| ' flag : ' || v_type(i).flag);
end loop;
-- 由下面的测试可知 v_type(i)不用看做是一个真正临时表
/*declare
v_id v_type(1).id%type;-- 声明变量就出错
v_name v_type(1).name%type;
v_flag v_type(1).flag%type;
begin
select id,name,flag into v_id,v_name,v_flag from v_type(1);
dbms_output.put_line('v_id : ' || v_id ||
' v_name : ' || v_name || ' v_flag : ' || v_flag);
--insert into v_type(2)(id,name,flag) values(11,'kkk','3');
--commit;
end;*/
end;
定义TABLE类型实例1--存储多列多行和RECORD结合使用:
declare
-- 按照前面的record的认识,这里定义相当于定义一个对象
type v_test is record(
test_id testkd.id%type,
test_name testkd.name%type,
test_flag testkd.flag%type
);
-- 定义一个table类型(即表结构),它的列来自于v_test
type t_type is table of v_test;
-- 声明t_type类型的变量
v_type t_type;
begin
select id,name,flag bulk collect into v_type
from testkd
where testkd.id <= 5;
for i in v_type.first .. v_type.last loop
dbms_output.put_line('id : ' || v_type(i).test_id
|| ' name : ' || v_type(i).test_name
|| ' flag : ' || v_type(i).test_flag);
end loop;
end;
-- 显然这种方式比上面的rowtype方式麻烦些
注意事项:
VARRAY和TABLE集合不能直接对其进行查询,除非写死下标,那样的话没有多大意义。最好对其进行遍历。
网友评论