在oracle 11.2中,oracle總共提供了三種集合類型:varray,嵌套表,聯合數組。所謂集合,簡單來說就是保存多行數據的數據類型,相當於保存在內存中的小型表,便於暫時保存數據,以及數據的重複使用。下面的表簡單描述了其中的區別與聯繫:
類型
|
|
保存數據類型數量
|
長度
|
創建實例
|
|
標量集合
|
varry
|
一種
|
固定長度(長度使用extend方法增加)
|
一維數組(相當於類,有其方法和構造方法【類型名】)
序號連續
對象類型
|
create or replace type type_name as varry(3) of varchar(20)或者在程序的定義區中聲明:
type type_name is varry(3) of varchar(20);
初始化:object_name type_name :=type_name();
賦值: object_name(i):=n;
|
標量集合
|
嵌套表
|
一種
|
長度沒有限制
|
一維數組(相當於類,有其方法和構造方法【類型名】)
序號連續
對象類型
|
create or replace type type_name as table of varchar(20)或者在程序的定義區中聲明:
type type_name is table of varchar(20)
初始化:object_name type_name :=type_name();
賦值: object_name type_name :=type_name();
|
標量集合
|
關聯數組
|
一種
|
長度沒有限制
|
一維列表
序號不連續,刪除會斷續
非對象類型,只能用於PL/SQL
|
只能在程序的定義區中聲明:
type type_name is table of varchar(20)index by binary_integer
初始化:object_name type_name;
賦值: object_name:=n;
|
對象類型集合
|
SQL嵌套表
|
多種
|
長度沒有限制
|
列表(跟table很像)
多維數組
SQL記錄集合
|
1、創建對象類型
create or replace type object_type_name is object
(
column_name number,
column_name char
);
2、創建SQL級別的對象類型集合
create or replace type object_type_name_table is table of object_type_name;
3、初始化
object_name object_type_name_table :=object_type_name_table ();
4、賦值
object_name(i):=object_type_name (i,i,i);
|
對象類型集合
|
PL/SQL嵌套表
|
多種
|
長度沒有限制
|
列表(跟table很像)
多維數組
SQL記錄集合
|
1、3、4同上
2、創建PL/SQL級別的對象類型集合:聲明
type object_type_name_table is table of object_type_name
|
對象類型集合
|
記錄類型集合
|
多種
|
一行數據
|
相當於數據庫表中的一行數據
非對象類型
(只能在PL/SQL中使用)
|
1、聲明(在一個包中創建)
type recorde_name is record
(
column_name number,
column_name char
);
type object_recorde_name is table of recorde_name index by PLS_INTEGER;
2、初始化
object_name object_recorde_name;
3、賦值
object_name(i)=i;
|
1、varray固定數組
簡單來說,varray就是一維數組,保存一種數據類型的數據,長度固定。聲明的時候若爲空數組,則表示還沒有分配空間,需要手工分配空間extend,否則會報錯。另外需要注意的是,該數組的下標是從1開始的。
set serveroutput on;
declare
no int :=1;
type fixed_array is varray(4) of char(2);---varray固定數組類型定義;
Farray fixed_array :=fixed_array();---varray固定數組聲明,這裏定義的數組爲空數組,並沒有分配任何空間
begin
for i in (select distinct COUNTRY_ISO_CODE from countries where rownum<4)loop
farray.extend;---分配空間,不能訪問空數組,所以空數組的場合,必須進行數組擴展
farray(no):=i.COUNTRY_ISO_CODE;---下標從1開始,不能超過數組所有元素的總和,當下標超出允許範圍時,出現異常:ORA-06532: Subscript outside of limit
no := no+1;
end loop;
dbms_output.put_line('分配的空間:'|| farray.count);---count這個API方法是輸出所分配的空間;
for i in 1..farray.count loop ----輸出結果值;
dbms_output.put('/'||farray(i));
if i=farray.count then
dbms_output.new_line;
end if;
end loop;
end;
anonymous block completed
分配的空間:3
/US/DE/GB
2、可變數組
顧名思義,就是數組的長度沒有限制。其中有兩種集合類型,一是嵌套表,二是聯合數組。跟上面的varray一樣,數組的下標從1開始。不過,聯合數組的序號有可能是不連續的,刪除了其中的某個元素之後就不連續了。
/**嵌套表作爲標量集合的時候,跟上面的varray差不多。
**聲明是若爲空數組,則需要分配空間;
**不同的是,分配的空間沒有限制
**/
set serveroutput on;
declare
no int :=1;
type variable_array is table of char(2);--沒有空間分配的限定設置
vtable variable_array :=variable_array();
begin
for i in (select distinct COUNTRY_ISO_CODE from countries where rownum<5)loop
vtable.extend; --分配空間
vtable(no):=i.COUNTRY_ISO_CODE;
no := no+1;
end loop;
dbms_output.put_line('分配的空間:'|| vtable.count);---可以看到結果爲4
for i in 1..vtable.count loop
dbms_output.put('/'||vtable(i));
if i=vtable.count then
dbms_output.new_line;
end if;
end loop;
end;
anonymous block completed
分配的空間:4
/US/DE/GB/NL
/**聯合數組存在這比較多的不同:
**1、聲明方式不一樣;
**2、不用顯式分配空間
**3、刪除之後,空間被回收,但是序號依然存在,爲此輸出值的時候需要注意這些不存在值的序號,否則會報錯
**/
set serveroutput on;
declare
no int :=1;
type variable_array is table of char(2) index by binary_integer;--沒有空間分配的限定設置
vtable variable_array ;---聲明的方式有所不同;
begin
for i in (select distinct COUNTRY_ISO_CODE from countries where rownum<6)loop
----vtable.extend; --分配空間
vtable(no):=i.COUNTRY_ISO_CODE;
no := no+1;
end loop;
dbms_output.put_line('分配的空間:'|| vtable.count);---可以看到結果爲5
vtable.delete(2);
dbms_output.put_line('刪除後分配的空間:'|| vtable.count);---可以看到結果爲4,即已經回收了刪除的空間
if vtable.exists(2)=false then
dbms_output.put_line('刪除之後的元素不再存在');----可以看到該元素已經不存在
end if;
for i in 3..vtable.count loop ---如果這裏包含不存在的元素2的話,會報錯。
dbms_output.put('/'||vtable(i));
if i=vtable.count then
dbms_output.new_line;
end if;
end loop;
end;
3、記錄
record,保存的是一行數據。與%TYPE,%ROWTYPE用起來比較方便。可以隨着表列類型的更新而更新。
/**record只是保存返回的一行記錄;
**不過,record比較方便的就是其類型可以隨着表列類型的更新而更新;
**/
set serveroutput on;
declare
OneRow countries%rowtype;---該record類型對應的是表的所有列;
type Rrecord is record( ---定義record類型,只是某些表的某些列;
code countries.COUNTRY_ISO_CODE%type,
name countries.COUNTRY_NAME%type
);
country Rrecord;---聲明對象;
begin
select * into OneRow from countries where rownum<2;----注意,只能往其中輸入一行數據,否則會報錯:ORA-01422: 實際返回的行數超出請求的行數;
select country_iso_code,country_name into country from countries where rownum<2;--部分列
dbms_output.put_line('國家ID:'||country.code);
dbms_output.put_line('國家名稱:'||country.name);
end;
anonymous block completed
國家ID:US
國家名稱:United States of America
4、保存列表數據
上面提到的都是保存一維數組,如果需要保存多維數組的話,可以利用嵌套來實現。
record+varray/嵌套表/聯合數組。三種集合類型用法比較相似,爲此只是對varray舉例
declare
no int :=1;
type Rrecord is record(
code countries.COUNTRY_ISO_CODE%type,
name countries.COUNTRY_NAME%type);----定義record記錄類型
type var is varray(3) of Rrecord;-----定義記錄集合數組
multirow var := var();----------------聲明記錄集合數組
begin
multirow.extend(3);---分配空間;
select country_iso_code,country_name BULK COLLECT INTO multirow from countries where rownum<4;---批量插入數據;
----輸出結果
for i in 1..multirow.count loop
dbms_output.put_line(i||' code:'||multirow(i).code||' name: '||multirow(i).name);
end loop;
end;
anonymous block completed
1 code:US name: United States of America
2 code:DE name: Germany
3 code:GB name: United Kingdom