復合類型
復合類型可以存儲多個值,包括記錄和集合。集合是一維的,但是可以在集合中放入其它集合,變成多維集合。集合又分為索引表、嵌套表和變長數組三種。要使用集合,我們首先要創建集合類型,然後聲明該類型的變量。我們可以在任何PL/SQL塊、子程序或包的聲明部分使用TABLE和VARRAY關鍵字來聲明集合類型。集合的作用域和同其他類型變量一樣,在一個塊或子程序中,當程序進入塊或子程序時有效,退出時失效。在包中,集合在我們第一次引用包的時候有效,直至會話終止時才失效。
一、記錄
記錄可以包括多個成員,從而可以保存多個值。記錄中的成員的數據類型可以不同。記錄在使用時必須先聲明記錄類型,然後定義記錄變量,最後才能在PL/SQL中使用。
示例1:
DECLARE
TYPE MyRecord IS RECORD(
name VARCHAR2(10),
age SMALLINT
);
mr MyRecord;
BEGIN
mr.name:='zhangsan';
mr.age:=20;
DBMS_OUTPUT.PUT_LINE('姓名:'||mr.name||' 年齡:'||mr.age);
END;
示例2: DECLARE
TYPE MyRecord IS RECORD(
no NUMBER(2),
name VARCHAR2(14),
city scott.dept.loc%TYPE
);
deptRecord MyRecord ;
BEGIN
--SELECT 語句後列的數目與記錄中的變量數目相同
SELECT deptno,dname,loc into deptRecord FROM DEPT WHERE DEPTNO=30;
DBMS_OUTPUT.PUT_LINE(deptRecord.no||':'||deptRecord.name||':'||deptRecord.city);
END;
示例3:
DECLARE
TYPE MyRecord IS RECORD(
no NUMBER(2),
name VARCHAR2(14),
city scott.dept.loc%TYPE
);
deptRecord MyRecord;
BEGIN
--SELECT 語句後列的數目少於記錄中的變量數目
SELECT dname,loc INTO deptRecord.name,deptRecord.city FROM DEPT WHERE DEPTNO=30;
deptRecord.no:=30;
DBMS_OUTPUT.PUT_LINE(deptRecord.no||':'||deptRecord.name||':'||deptRecord.city);
END;
示例4:
DECLARE
--特殊定義記錄方式,記錄中變量的類型與dept表行的類型相同
deptRecord dept%ROWTYPE;
BEGIN
SELECT * INTO deptRecord FROM DEPT WHERE DEPTNO=30;
DBMS_OUTPUT.PUT_LINE(deptRecord.deptNo||':'||deptRecord.dname||':'||deptRecord.loc);
END;
二、索引表(關聯數組)
索引表就是鍵值集合,鍵是唯一的,用於查找對應的值。鍵可以是整數或字符串。第一次使用鍵來指派一個對應的值就是添加元素,而後續這樣的操作就是更新元素。
DECLARE
TYPE MyTableTypeName IS TABLE OF ElementType [NOT NULL]
INDEX BY Key_Type;
myName MyTableTypeName;
其中:MyTableTypeName是表類型的名稱,ElementType是元素的數據類型,NOT NULL表示不允許引用NULL值,Key_Type是下標的數據類型,BINARY_INTEGER PLS_INTEGER或VARCHAR2(Oracle9i及以後版本可用)。myName是表類型變量名。
示例1
DECLARE
TYPE MyTabelType IS TABLE OF dept.dname%TYPE
NOT NULL INDEX BY BINARY_INTEGER;
my MyTabelType;
BEGIN
SELECT DNAME INTO my(-3) FROM DEPT WHERE deptno=20;
SELECT DNAME INTO my(-1) FROM DEPT WHERE deptno=40;
DBMS_OUTPUT.PUT_LINE('my(-3):'||my(-3));
DBMS_OUTPUT.PUT_LINE('my(-1):'||my(-1));
END;
示例2:
DECLARE
TYPE MyTableType IS TABLE OF NUMBER
NOT NULL INDEX BY VARCHAR2(20);
my MyTableType;
BEGIN
my('China'):=1;
my('Japan'):=2;
my('USA'):=3;
DBMS_OUTPUT.PUT_LINE(my.first);
DBMS_OUTPUT.PUT_LINE(my.last);
DBMS_OUTPUT.PUT_LINE(my('China'));
DBMS_OUTPUT.PUT_LINE(my(my.last));
END;
三、嵌套表
要使用嵌套表,首先要創建嵌套表類型,其次聲明嵌套表類型變量,然後初始化嵌套表變量,最後引用嵌套表變量元素值。
1、定義嵌套表類型
TYPE MyNestedTableType IS TABLE OF ElementType [NOT NULL];
其中:
MyNestedTableType是嵌套表類型的名稱。ElementType是嵌套表元素的類型,它是可以除了REF CURSOR類型之外的任何PL/SQL類型,但是對於全局嵌套表(CREATE TYPE創建)來說,以下類型也是不允許的:BINARY_INTEGER PLS_INTEGER BOOLEAN LONG LONG RAW NATURAL NATURALN POSITIVE POSITIVEN REF CURSOR SIGNTYPE STRING 。NOT NULL表示元素值不能為NULL。
示例:
DECLARE
--定義記錄
TYPE DeptRecord IS RECORD(
no NUMBER(2),
name VARCHAR2(14),
city scott.dept.loc%TYPE
);
--定義游標
CURSOR DeptCursor IS SELECT * FROM DEPT;
--定義嵌套表元素類型時使用%TYPE
TYPE DNameList IS TABLE OF dept.dname%TYPE;
--定義嵌套表元素類型時使用表的%ROWTYPE
TYPE DeptList1 IS TABLE OF DEPT%ROWTYPE;
--定義嵌套表元素類型時使用游標的%ROWTYPE
TYPE DeptList2 IS TABLE OF DeptCursor%ROWTYPE;
--定義嵌套表元素類型時使用記錄類型
TYPE DeptList3 IS TABLE OF DeptRecord ;
--在SQL語句中定義嵌套表類型
CREATE TYPE PhoneList IS TABLE OF VARCHAR2(10);
2、聲明嵌套表類型變量
示例:
DECLARE
TYPE DNameList IS TABLE OF dept.dname%TYPE;
nameList1 DNameList;
nameList2 nameList1%TYPE; --使用%TYPE聲明嵌套表類型變量
--在存儲過程參數中定義嵌套表類型變量
CREATE OR REPLACE PROCEDURE proc_name(nameList IN DNameList)
注意:不能將嵌套表類型和嵌套表類型變量同名,大小寫不同也不可,因PL/SQL不區分大小寫
3、初始化嵌套表類型變量
嵌套表必須先通過構造方法初始化(索引表不需要通過構造方法進行初始化),否則嵌套表變量為NULL,在初始化中元素個數沒有限制。
示例:
DECLARE
TYPE DNameList IS TABLE OF dept.dname%TYPE;
my DNameList ;
BEGIN
my:=DNameList('CORESUN','CORESUN','CORESUN');
注意:my變量在初始化時傳入了3個參數,那麼嵌套表長度就是3,以後使用時長度不夠,必須通過extend函數進行擴展長度。如果在構造方法中沒有傳入任何參數,則嵌套表長度為0。
也可以在聲明聲明嵌套表類型變量的同時進行初始化,如:
my DNameList:=DNameList('CORESUN','CORESUN','CORESUN');
如果定義元素類型時沒有指定NOT NULL,在構造方法中也可以傳入NULL,如:
my:=DNameList('CORESUN',NULL,'CORESUN');
4、引用嵌套表類型變量
通過嵌套表變量和圓括號裡的索引值來引用嵌套表中的元素,嵌套表的下標是從1開始編號,最大至231 ,下標可以是一個整數,也可以是整數表達式。
示例:
DECLARE
TYPE DNameList IS TABLE OF dept.dname%TYPE;
my DNameList ;
BEGIN
my:=DNameList(NULL,'CORESUN','CORESUN');
SELECT DNAME INTO my(2) FROM dept where deptno=20;
my(1):='CORESUN';
--my(4):='CORESUN';
DBMS_OUTPUT.PUT_LINE(my(1));
DBMS_OUTPUT.PUT_LINE(my(2));
END;
四、嵌套表應用示例
示例1:創建記錄類型的嵌套表
DECLARE
TYPE DeptRecord IS RECORD(
no NUMBER(2),
name VARCHAR2(14),
city scott.dept.loc%TYPE
);
TYPE DeptRecordList IS TABLE OF DeptRecord;
示例2:嵌套表用在另一個表的內部
1、創建全局嵌套表類型
--當嵌套表作為表列的類型時,要先創建,這樣的嵌套表我們稱為全局嵌套表
CREATE OR REPLACE TYPE PHONE_TYPE IS TABLE OF VARCHAR2(20);
/
CREATE TABLE person
(
id NUMBER,
name VARCHAR2(10),
sal NUMBER(6,2),
phone PHONE_TYPE
) NESTED TABLE phone STORE AS PHONE_TABLE;
2、向person表插入數據:
INSERT INTO person VALUES(1,'SCOTT',800,PHONE_TYPE('13256789876','031198765432'));
INSERT INTO PERSON VALUES(20,'CORESUN',2000,PHONE_TYPE('13999999999','13098765345','01064890987'));
3、查詢嵌套表列的數據:
查詢全部的列信息
SELECT * FROM PERSON;
在isql*plus中結果如下:
通過嵌套表變量顯示信息
DECLARE
pTable PHONE_TYPE;
BEGIN
SELECT phone into pTable FROM person WHERE name='SCOTT';
FOR i IN 1..pTable.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('號碼'||i||':'||pTable(i));
END LOOP;
結果如下:
號碼1:13256789876
號碼2:031198765432
4、更新嵌套表數據:
DECLARE
pTable PHONE_TYPE:=PHONE_TYPE('034223455432','13888888888');
BEGIN
UPDATE person SET phone=pTable WHERE name='SCOTT';
END;
四、可變數組(VARRAY數組)
VARRAY數組是一種集合數據類型,也可以作為表的列來使用,該集合的下標從1開始,並且元素個數是有限制的。語法如下:
DECLARE
TYPE MyArrayTypeName IS VARRAY(size) OF ELEMENT_TYPE [NOT NULL];
my MyArrayTypeName
其中MyArrayTypeName 是數組類型的名字,size表示數組最多存儲多少個元素,ELEMENT_TYPE是元素的類型,NOT NULL不允許使用NULL值,my是數組變量的名稱。
示例1:
DECLARE
TYPE MyVArrayType IS VARRAY(10) OF dept.dname%TYPE NOT NULL;
--構造方法中最多可以有10(size)個元素
--既是沒有定義NOT NULL,也不會自動為4-10元素賦NULL值
nameArray MyVArrayType:=MyVArrayType('1','2','3');
BEGIN
SELECT dname into nameArray(1) from dept where deptno=20;
SELECT dname into nameArray(2) from dept where deptno=30;
DBMS_OUTPUT.PUT_LINE(nameArray(1));
DBMS_OUTPUT.PUT_LINE(nameArray(2));
DBMS_OUTPUT.PUT_LINE(nameArray(3));
END;
結果如下: RESEARCH
SALES
3