関連配列とは、一連のキーと値のペアからなる集合です。各キーは一意であり、対応するデータを格納する要素のインデックスとして使用されます。
適用対象
この内容はOceanBaseデータベースEnterprise Editionにのみ適用されます。OceanBaseデータベースCommunity Editionでは、MySQLモードのみが提供されています。
variable_name(index)構文を使用することで、その一意のインデックスを通じて集合変数の各要素にアクセスできます。これにより、配列内の位置を知る必要も、配列全体をイテレーションする必要もありません。
キーのデータ型はPLS_INTEGERまたはVARCHAR2とすることができます。詳細は以下のとおりです:
キーのデータ型が
PLS_INTEGERの場合、関連配列は整数インデックス(Indexed by Integer)であり、かつ密な(要素間に隙間がない)ものであるため、最初の要素から最後の要素までの各要素は定義されており、値を持ちます(値はNULLにすることもできます)。キーのデータ型が
VARCHAR2の場合、関連配列は文字列インデックス(Indexed by String)であり、かつ疎な(要素間に隙間がある可能性がある)ものです。説明
密な関連配列をイテレーションする際は、要素間の隙間を考慮する必要はありません。疎な関連配列をイテレーションする際は、隙間に注意する必要があります。
関連配列要素への代入
以下の代入式を使用して、関連配列の要素に値を代入できます:
array_name(key) := value
キーが配列内に存在しない場合、代入ステートメントは配列にキーと値のペアを追加します。キーが存在する場合、代入ステートメントはそのキーに対応する値を新しい値に更新します。
特に、関連配列は一時的なデータストレージに使用でき、テーブルのようにスペースやネットワークリソースを占有する必要はありません。ただし、関連配列は一時的なストレージ用であるため、DMLステートメントによる操作はできません。
パッケージ内で関連配列変数を定義し、パッケージ本体で代入すると、関連配列はデータベースセッション期間中可視されます。そうでない場合は、所属するサブプログラムの範囲内でのみ可視されます。
関連配列の宣言
関連配列を宣言するには、まず関連配列の型を宣言し、次にその型の変数を宣言する必要があります。最もシンプルな構文は以下のとおりです:
TYPE array_type IS TABLE OF element_type INDEX BY key_type;
array_name array_type;
例:関連配列の宣言
obclient> DECLARE
TYPE TYPE_SALARY IS TABLE OF NUMBER -- 関連配列の型
INDEX BY VARCHAR2(64); -- インデックスのタイプは文字列
salary TYPE_SALARY; -- 関連配列変数
n VARCHAR2(64); -- スカラ変数
BEGIN
-- 関連配列にキーと値のペアを追加
salary('Tom') := 2000;
salary('Mike') := 7500;
salary('Steve') := 10000;
-- 関連配列を出力
n :=salary.FIRST; -- 関連配列の最初の要素を取得
WHILE n IS NOT NULL
LOOP
DBMS_OUTPUT.PUT_LINE('Salary of ' || n || ' is ' || salary(n));
n := salary.Next(n); -- 関連配列の次の要素を取得
END LOOP;
END;
/
Query OK, 0 rows affected
Salary of Mike is 7500
Salary of Steve is 10000
Salary of Tom is 2000
関連配列の埋め込み
密な関連配列を埋め込む最も効果的な方法は、SELECT [FETCH] BULK COLLECT INTO 句を使用することです。
説明
密な関連配列に大量のデータを埋め込む場合、SELECT ステートメントで返される結果セットがメモリサイズを超える可能性があるため、カーソルと FETCH ステートメントを使用し、BULK COLLECT INTO および LIMIT 句を組み合わせて SELECT ステートメントに代えることができます。
疎な関連配列を埋め込む際は SELECT ステートメントを使用できません。その代わりに、FOR LOOP ループステートメント内で代入ステートメントを使用できます。
以下の例では、SELECT ステートメントを使用して整数インデックスの関連配列を埋め込み、次に FOR LOOP ステートメントを使用して文字列インデックスの疎な関連配列を埋め込みます。
例:関連配列の埋め込み
obclient> CREATE TABLE emp(
emp_id NUMBER NOT NULL);
Query OK, 0 rows affected
obclient>INSERT INTO emp VALUES(101),(102),(103),(103),(102);
Query OK, 5 rows affected
Records: 5 Duplicates: 0 Warnings: 0
obclient>DECLARE
TYPE num_table IS TABLE OF emp.emp_id%TYPE
INDEX BY BINARY_INTEGER; -- 関連配列のインデックスタイプを整数型として定義
num_list NUM_TABLE; -- 関連配列の変数を定義
BEGIN
SELECT emp_id
BULK COLLECT INTO num_list from emp;
DBMS_OUTPUT.PUT_LINE('Bulk Collected:');
FOR i IN num_list.FIRST..num_list.LAST LOOP
IF i <= 3 THEN
DBMS_OUTPUT.PUT_LINE('Number ['||num_list(i)||']');
END IF;
END LOOP;
END;
/
Query OK, 0 rows affected
Bulk Collected:
Number [101]
Number [102]
Number [103]
密集連想配列のイテレーション
密集連想配列(整数型インデックス)の要素間には隙間がなく、最初の要素と最後の要素の間にある各要素には定義と値(この値はNULLにすることもできます)があります。FOR LOOPステートメントを使用して密集連想配列をイテレーションできます。
次の例では、FOR LOOPステートメントを使用して連想配列の各要素値を出力します。ここで、FOR LOOPステートメントの上限tab_wares.COUNTは、セットのメソッドCOUNTを呼び出して配列内の要素数を返します。
例:密集連想配列のイテレーション
obclient> CREATE TABLE ware (
w_id INT NOT NULL,
w_name VARCHAR(10),
w_city VARCHAR(20),
w_state VARCHAR(20),
PRIMARY KEY(w_id)
);
Query OK, 0 rows affected
obclient>INSERT INTO ware VALUES(1,'KING','BeiJing','China');
Query OK, 1 row affected
obclient>INSERT INTO ware VALUES(2,'ALLEN','ShangHai','China');
Query OK, 1 row affected
obclient>INSERT INTO ware VALUES(3,'CLARK','ShangHai','China');
Query OK, 1 row affected
obclient>SET SERVEROUTPUT ON;
Query OK, 0 rows affected
obclient>DECLARE
-- カーソルなしで連想配列を宣言
TYPE type_ware IS TABLE OF ware%ROWTYPE INDEX BY PLS_INTEGER ;
tab_wares TYPE_WARE;
TYPE type_ware_city IS TABLE OF ware.w_city%TYPE INDEX BY VARCHAR(20);
tab_ware_cities TYPE_WARE_CITY;
TYPE type_ware_name IS TABLE OF ware.w_name%TYPE INDEX BY VARCHAR(20);
ware_names TYPE_WARE_NAME;
BEGIN
SELECT w_id,w_name,w_city,w_state BULK COLLECT INTO tab_wares FROM ware;
FOR i IN 1..tab_wares.COUNT LOOP
dbms_output.put_line(
rpad( tab_wares(i).w_id, 23)
|| rpad( tab_wares(i).w_name, 23)
|| rpad(tab_wares(i).w_city, 23 )
);
END LOOP;
END;
/
Query OK, 0 rows affected
1 KING BeiJing
2 ALLEN ShangHai
3 CLARK ShangHai
疎ベクトルのイテレーション
疎ベクトル(文字列インデックス)では、要素間に空きが存在する可能性があります。そのため、WHILE LOOP ステートメントと集合のメソッド FIRST および NEXT を組み合わせて疎ベクトルをイテレーションする必要があります。例は以下のとおりです:
DECLARE
-- カーソルなしで関連配列を宣言
TYPE type_ware IS TABLE OF ware%ROWTYPE INDEX BY PLS_INTEGER ;
tab_wares TYPE_WARE;
TYPE type_ware_city IS TABLE OF ware.w_city%TYPE INDEX BY VARCHAR(20);
tab_ware_cities TYPE_WARE_CITY;
TYPE type_ware_name IS TABLE OF ware.w_name%TYPE INDEX BY VARCHAR(20);
-- 宣言部分に追加:
i_name ware.w_name%TYPE;
BEGIN
SELECT w_id,w_name,w_city,w_state
BULK COLLECT INTO tab_wares FROM ware;
FOR i IN 1..tab_wares.COUNT LOOP
dbms_output.put_line(
rpad( tab_wares(i).w_id, 23)
|| rpad( tab_wares(i).w_name, 23)
|| rpad(tab_wares(i).w_city, 23 )
);
END LOOP;
-- 実行部分に追加:
i_name := tab_ware_cities.FIRST ;
WHILE i_name IS NOT NULL LOOP
dbms_output.put_line(rpad(i_name,12) || tab_ware_cities(i_name) );
i_name := tab_ware_cities.NEXT(i_name);
END LOOP;
END;
/
Query OK, 0 rows affected
1 KING BeiJing
2 ALLEN ShangHai
3 CLARK ShangHai