关联数组 (PL/SQL)
PL/SQL 关联数组是一种集合类型,它使唯一的键与值相关联。
关联数组具有下列特征:
- 必须先定义关联数组类型,然后才能声明具有该数组类型的数组变量。数据处理在数组变量中进行。
- 无需对此数组进行初始化;只需将值指定给数组元素。
- 对此数组中的元素数目没有已定义的限制;此数组可以在添加元素时动态地增大。
- 此数组可以是稀疏数组;即,对键进行的赋值可以有间隔。
- 尝试引用尚未进行赋值的数组元素将导致异常。
请使用 TYPE IS TABLE OF 语句来定义关联数组类型。
语法
描述
- TYPE 关联类型
- 指定数组类型的标识。
- datatype
- 指定受支持的数据类型,例如 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 属性。
要声明具有关联数组类型的变量,请指定
数组名 关联类型,其中
数组名 表示对关联数组指定的标识,关联类型
表示先前声明的数组类型的标识。
要引用数组的特定元素,请指定 数组名(n),其中
数组名 表示先前声明的数组的标识,n 表示 INDEX BY 数据类型为
关联类型 的值。如果根据记录类型来定义数组,那么该引用将变为
数组名(n).字段,其中
字段 在数组类型的定义所基于记录类型中定义。要引用整个记录,请省略 字段。
示例
以下示例从 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 /