連想配列 (PL/SQL)
PL/SQL 連想配列とは、ユニーク・キーを値と関連付けるコレクション・タイプのことです。
連想配列には以下の特性があります。
- 連想配列タイプを定義した後でなければ、その配列タイプの配列変数を宣言できません。 配列変数内でデータ操作が行われます。
- 配列を初期設定する必要はありません。配列エレメントに値を割り当てるだけです。
- 配列内のエレメント数について、定義された制限はありません。エレメントを追加するにつれて、エレメント数は動的に増加します。
- 配列は疎 であっても構いません。すなわち、キーに対する値の割り当てに間隔があっても構いません。
- 値が割り当てられていない配列エレメントを参照しようとすると、例外が発生します。
TYPE IS TABLE OF ステートメントを使用して、連想配列タイプを定義します。
構文
説明
- TYPE assoctype
- 配列タイプの ID を指定します。
- datatype
- サポートされるデータ・タイプ (VARCHAR2、NUMBER、RECORD、VARRAY、または連想配列タイプなど) を指定します。 %TYPE 属性および %ROWTYPE 属性もサポートされます。
- INDEX BY
- この節によって導入されるデータ・タイプの 1 つによって、連想配列を索引付けすることを指定します。
- BINARY INTEGER
- 整数値データ。
- PLS_INTEGER
- 整数値データ。
- VARCHAR2 (n[BYTE|CHAR])
- 最大長 n コード単位の可変長文字ストリング。最大長は、1 から 32672 までの BYTE、または 1 から 8168 までの CHAR の範囲で指定できます。 %TYPE 属性の適用対象となるオブジェクトが、BINARY_INTEGER、PLS_INTEGER、または VARCHAR2 データ・タイプである場合、%TYPE 属性もサポートされます。
連想配列タイプの変数を宣言するには、array-name assoctype と指定します。ここで、array-name は連想配列に割り当てる ID を表し、assoctype は既に宣言されている配列タイプの ID を表します。
配列に含まれる特定のエレメントを参照するには、array-name(n) と指定します。ここで、array-name は既に宣言されている配列の ID を表し、n は assoctype の INDEX BY データ・タイプの値を表します。 レコード・タイプから配列が定義されている場合は、参照は array-name(n).field となります。ここで、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_rec_typ レコード・タイプを使用する代わりに、emp%ROWTYPE 属性を使用して emp_arr_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
/