关联数组 (PL/SQL)
PL/SQL 关联数组是一种集合类型,它使唯一的键与值相关联。
关联数组具有下列特征:
- 必须先定义关联数组类型,然后才能声明具有该数组类型的数组变量。 数据处理在数组变量中进行。
- 无需对此数组进行初始化;只需将值指定给数组元素。
- 对此数组中的元素数目没有已定义的限制;此数组可以在添加元素时动态地增大。
- 此数组可以是稀疏数组;即,对键进行的赋值可以有间隔。
- 尝试引用尚未进行赋值的数组元素将导致异常。
请使用 TYPE IS TABLE OF 语句来定义关联数组类型。
语法
描述
- 类型 assoctype
- 指定数组类型的标识。
- 数据类型
- 指定受支持的数据类型,例如 VARCHAR2、NUMBER、RECORD、VARRAY 或关联数组类型。 另外,还支持 %TYPE 属性和 %ROWTYPE 属性。
- INDEX BY
- 指定关联数组按此子句所引入的其中一种数据类型建立索引。
- BINARY INTEGER
- 整型数字数据。
- PLS_INTEGER
- 整型数字数据。
- VARCHAR2 (n[BYTE | CHAR])
- 最大长度为 n 个代码单元的可变长度字符串,可介于 1 到 32 672 字节或者 1 到 8 168 个字符。 如果 %TYPE 属性所应用于的对象具有 BINARY_INTEGER、PLS_INTEGER 或 VARCHAR2 数据类型,那么还支持 %TYPE 属性。
要声明具有关联数组类型的变量,请指定 array-name assoctype,其中 array-name 表示分配给关联数组的标识, assoctype 表示先前声明的数组类型的标识。
要引用数组的特定元素,请指定 array-name(n),其中 array-name 表示先前声明的数组的标识, n 表示 INDEX BY 数据类型 assoctype的值。 如果从记录类型定义数组,那么引用将变为 array-name(n).field,其中 field 是在定义数组类型的记录类型中定义的。 要引用整个记录,请省略 字段。
示例
以下示例从 EMP 表中读取前 10 个职员姓名,将其存储在数组中,然后显示数组内容。
SET SERVEROUTPUT ON
/
CREATE OR REPLACE PACKAGE pkg_test_type1
IS
TYPE emp_arr_typ IS TABLE OF VARCHAR2(10) INDEX BY BINARY_INTEGER;
END pkg_test_type1
/
DECLARE
emp_arr pkg_test_type1.emp_arr_typ;
CURSOR emp_cur IS SELECT ename FROM emp WHERE ROWNUM <= 10;
i INTEGER := 0;
BEGIN
FOR r_emp IN emp_cur LOOP
i := i + 1;
emp_arr(i) := r_emp.ename;
END LOOP;
FOR j IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(emp_arr(j));
END LOOP;
END
/此代码生成以下样本输出:SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER可以对此示例进行修改,以便在数组定义中使用记录类型。
SET SERVEROUTPUT ON
/
CREATE OR REPLACE PACKAGE pkg_test_type2
IS
TYPE emp_rec_typ IS RECORD (
empno INTEGER,
ename VARCHAR2(10)
);
END pkg_test_type2
/
CREATE OR REPLACE PACKAGE pkg_test_type3
IS
TYPE emp_arr_typ IS TABLE OF pkg_test_type2.emp_rec_typ INDEX BY BINARY_INTEGER;
END pkg_test_type3
/
DECLARE
emp_arr pkg_test_type3.emp_arr_typ;
CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10;
i INTEGER := 0;
BEGIN
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME');
DBMS_OUTPUT.PUT_LINE('----- -------');
FOR r_emp IN emp_cur LOOP
i := i + 1;
emp_arr(i).empno := r_emp.empno;
emp_arr(i).ename := r_emp.ename;
END LOOP;
FOR j IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(emp_arr(j).empno || ' ' ||
emp_arr(j).ename);
END LOOP;
END
/修改后的代码生成以下样本输出:EMPNO ENAME
----- -------
1001 SMITH
1002 ALLEN
1003 WARD
1004 JONES
1005 MARTIN
1006 BLAKE
1007 CLARK
1008 SCOTT
1009 KING
1010 TURNER可以进一步对此示例进行修改,以便使用 emp%ROWTYPE 属性来定义
emp_arr_typ,而不是使用 emp_rec_typ 记录类型。SET SERVEROUTPUT ON
/
CREATE OR REPLACE PACKAGE pkg_test_type4
IS
TYPE emp_arr_typ IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;
END pkg_test_type4
/
DECLARE
emp_arr pkg_test_type4.emp_arr_typ;
CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10;
i INTEGER := 0;
BEGIN
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME');
DBMS_OUTPUT.PUT_LINE('----- -------');
FOR r_emp IN emp_cur LOOP
i := i + 1;
emp_arr(i).empno := r_emp.empno;
emp_arr(i).ename := r_emp.ename;
END LOOP;
FOR j IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(emp_arr(j).empno || ' ' ||
emp_arr(j).ename);
END LOOP;
END
/在此情况下,样本输出与上一个示例完全相同。最后,可以进行从
r_emp 到 emp_arr 的记录级赋值,而不是对记录的每个字段逐个赋值:SET SERVEROUTPUT ON
/
CREATE OR REPLACE PACKAGE pkg_test_type5
IS
TYPE emp_rec_typ IS RECORD (
empno INTEGER,
ename VARCHAR2(10)
);
END pkg_test_type5
/
CREATE OR REPLACE PACKAGE pkg_test_type6
IS
TYPE emp_arr_typ IS TABLE OF pkg_test_type5.emp_rec_typ INDEX BY BINARY_INTEGER;
END pkg_test_type6
/
DECLARE
emp_arr pkg_test_type6.emp_arr_typ;
CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10;
i INTEGER := 0;
BEGIN
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME');
DBMS_OUTPUT.PUT_LINE('----- -------');
FOR r_emp IN emp_cur LOOP
i := i + 1;
emp_arr(i) := r_emp;
END LOOP;
FOR j IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(emp_arr(j).empno || ' ' ||
emp_arr(j).ename);
END LOOP;
END
/