1.Table(索引表)
索引表是將數據保存在內存中!!!
1.1 定義索引表
-- 定義記錄集
TYPE my_rec IS RECORD( ename varchar2(30), eid NUMBER );
-- 定義索引表類型
TYPE my_tab IS TABLE OF yang_rec INDEX BY BINARY_INTEGER;
-- 定義索引表對象的實例
test_tab my_tab;
1.2 將條目插入到索引表中
索引表中的每個元素都由一個唯一的整型值(索引)標識。引用表中的值時,必須提供該值的索引。
索引的範圍:1 ---- 2147483647,索引值可以不連續,同時PL/SQL並不爲沒有使用的條目預留空間。
例如:
---利用Cursor填寫索引表
DECLARE
CURSOR All_Emps IS
SELECT * FROM Employee ORDER BY Emp_Id;
TYPE Emp_Table IS TABLE OF Employee%ROWTYPE INDEX BY BINARY_INTEGER;
Emps Emp_Table;
Emps_Max BINARY_INTEGER;
BEGIN
Emps_Max := 0;
FOR Emp IN All_Emps
LOOP
Emps_Max := Emps_Max + 1;
Emps(Emps_Max).Emp_Id := Emp.Emp_Id;
Emps(Emps_Max).Emp_Name := Emp.Emp_Name;
END LOOP;
END;
/
1.3 對索引表中進行操作
1) 插入:見上例。
2) 引用:
IF emps.EXIST(10) THEN
DBMS_OUTPUT.PUT_LINE('存在第10條記錄。');
END IF;
3) 修改:
---修改emps 表中的第100個條目:
emps(100).emp_name := 'Chris Jian';
4) 刪除:
-- 刪除emps 表中的第100個條目:
emps.DELETE(100);
-- 刪除emps 表中的從1到100的條目:
emps.DELETE(1, 100);
-- 刪除emps 表中的的所有條目:
emps.DELETE;
1.4 索引表中的內建函數
1) count:返回表的條目數量:
num_rows := emps.COUNT;
2) EXISTS:如果指定的條目存在,則返回爲真;否則爲假。
IF emps.EXIST(10) THEN
DBMS_OUTPUT.PUT_LINE('存在第10條記錄。');
END IF;
3) LIMIT:該方法返回集合可以包含的最大元素數目。只有變長數組纔有上限。將LIMIT 用於嵌套表和索引
表時,其返回爲NULL。
4) FRIST:該方法返回集合中使用的最小的索引值。
5) LAST:該方法返回集合中使用的最大的索引值。
6) NEXT:該方法返回集合中當前使用的下一個索引值。
7) PRIOR:該方法返回集合中當前使用的上一個索引值。
8) DELETE:刪除集合中的條目,見前例。
9) TRIM:從集合的尾部刪除一個或多個條目,無返回值,只適用於變長數組和嵌套表。
emps.TRIM(1); -- 從集合的尾部刪除一個條目
emps.TRIM(3); -- 從集合的尾部刪除三個條目
10) EXTEND:在集合的尾部添加條目或複製已有的條目,只適用於變長數組和嵌套表。
emps.EXTEND(1); -- 從集合的尾部添加一個條目
emps.EXTEND(3); -- 從集合的尾部添加三個條目
emps.EXTEND(1, 3);-- 複製集合的第三個條目,並將其添加到表的末尾。
---------------------------
2 嵌套表
將數據保存在內存中!!!
嵌套表是一個無序記錄集合。
檢索數據庫中的嵌套表時,條目的索引是連續的,不能象索引表那樣隨意跳過索引值。
需要使用構造函數初始化嵌套表。
嵌套表不能是以下數據類型:
BOOLEAN, NCHAR, NCLOB, NVARCHAR2, REF CURSOR, TABLE, VARRAY, NOT NULL。
嵌套表的定義和索引表類似,但不能使用INDEX BY 子句。
2.1 初始化嵌套表
必須使用構造函數初始化嵌套表後,才能給它添加條目!
-- 定義索引表類型
TYPE emp_tab IS TABLE OF emp%ROWTYPE;
-- 定義索引表對象的實例
emps emp_tab;
-- 初始化嵌套表
emps := emp_tab();
2.2 擴展嵌套表
利用 EXTEND 來擴展嵌套表的數據於內存。
DECLARE
CURSOR All_Emps IS
SELECT * FROM Emp ORDER BY Empno;
TYPE Emp_Table IS TABLE OF Emp%ROWTYPE;
Emps Emp_Table;
i PLS_INTEGER;
l_Count PLS_INTEGER;
BEGIN
l_Count := 0;
Emps := Emp_Table(); -- 初始化嵌套表併產生一條空記錄
FOR C1 IN All_Emps
LOOP
l_Count := l_Count + 1;
Emps.EXTEND;
Emps(l_Count).Empno := C1.Empno;
Emps(l_Count).Ename := C1.Ename;
Emps(l_Count).Job := C1.Job;
Emps(l_Count).Mgr := C1.Mgr;
Emps(l_Count).Hiredate := C1.Hiredate;
Emps(l_Count).Sal := C1.Sal;
Emps(l_Count).Comm := C1.Comm;
Emps(l_Count).Deptno := C1.Deptno;
END LOOP;
-- clone the first entry five times
Emps.EXTEND(5, 1);
FOR i IN 1 .. l_Count + 5
LOOP
Dbms_Output.Put_Line(To_Char(Emps(i).Empno) || ' ' || Mps(i).Ename);
END LOOP;
END;
/
2.3 刪除嵌套表中的條目
1) DELETE 方法:
emps.DELETE(10); -- 刪除嵌套表中的第10個條目。
注意:在刪除嵌套表中的條目後,嵌套表中的條目並沒有重新編號,還可以繼續使用。
2) TRIM 方法:
TRIM方法是在表的末尾刪除指定數目的條目。
TRIM方法只能用於嵌套表和變長數組。
DECLARE
CURSOR All_Emps IS
SELECT * FROM Emp ORDER BY Empno;
TYPE Emp_Table IS TABLE OF Emp%ROWTYPE;
Emps Emp_Table;
i PLS_INTEGER;
l_Count PLS_INTEGER;
BEGIN
l_Count := 0;
-- 初始化嵌套表併產生一條空記錄
Emps := Emp_Table();
FOR C1 IN All_Emps
LOOP
l_Count := l_Count + 1;
Emps.EXTEND;
Emps(l_Count).Empno := C1.Empno;
Emps(l_Count).Ename := C1.Ename;
Emps(l_Count).Job := C1.Job;
Emps(l_Count).Mgr := C1.Mgr;
Emps(l_Count).Hiredate := C1.Hiredate;
Emps(l_Count).Sal := C1.Sal;
Emps(l_Count).Comm := C1.Comm;
Emps(l_Count).Deptno := C1.Deptno;
END LOOP;
-- clone the first entry five times
Emps.EXTEND(5, 1);
-- Trim off the five clones of entry #1
Emps.TRIM(5);
-- Delete the first entry
Emps.DELETE(1);
FOR i IN 1 .. l_Count + 5
LOOP
Dbms_Output.Put_Line(To_Char(Emps(i).Empno) || ' ' || Emps(i).Ename);
END LOOP;
END;
/
注意:調試以上代碼,並注意錯誤表達!!!
3 變長數組
變長數組與嵌套表類似,但變長數組的最大長度是固定的。
變長數組與嵌套表一樣需要初始化。
3.1 定義變長數組
-- 定義最大長度爲100 的變長數組
TYPE type_name IS VARRAY(100) OF VARCHAR2(20);
3.2 擴展變長數組
類似於嵌套表,但不能超過最大長度。例程類似於嵌套表的例程。
4 批綁定
PL/SQL 批綁定是Oracle8i中的新功能。
1) 使用 BULK COLLECT
2) 使用 FORALL
例程:
DECLARE
CURSOR C1 IS
SELECT Empno, Ename FROM Emp;
TYPE Eno_Tab IS TABLE OF Emp.Empno%TYPE;
TYPE Ename_Tab IS TABLE OF Emp.Ename%TYPE;
l_Enos Eno_Tab;
l_Enames Ename_Tab;
BEGIN
OPEN C1;
FETCH C1 BULK COLLECT
INTO l_Enos, l_Enames;
CLOSE C1;
FOR i IN 1 .. l_Enos.COUNT
LOOP
Dbms_Output.Put_Line(To_Char(l_Enos(i)) || ' ' || l_Enames(i));
END LOOP;
FORALL i IN l_Enos.FIRST .. l_Enos.LAST
UPDATE Emp SET Ename = l_Enames(i) WHERE Empno = l_Enos(i);
END;
/
5 集合的異常處理
異 常 原 因
COLLECTION_IS_NULL 在構造函數初始化集合之前試圖使用它
NO_DATA_FOUND 試圖訪問集合中不存在的條目
SUBCRIPT_BEYOND_COUNT 使用的下標超過了集合當前的元素數目
SUBCRIPT_OUTSIDE_LIMIT 變長數組中使用的下標大於該變長數組聲明中規定的最大值
VALUE_ERROR 使用一個不能轉換爲整形的下標