関連配列は、キーと値のペアの集合です。各キーは一意であり、対応するデータを格納する要素のインデックスを示します。
機能の適用範囲
この内容は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