コレクションはストアドプロシージャの複合変数であり、同じ型の複数の要素を順番に格納できる1次元配列のようなものです。コレクション全体はサブルーチンのパラメータとして渡すことができます。
適用対象
この内容はOceanBaseデータベースEnterprise Editionにのみ適用されます。OceanBaseデータベースCommunity EditionはMySQLモードのみを提供します。
コレクションの内部コンポーネントは要素と呼ばれ、各要素には一意のインデックスが付けられており、コレクション内での位置を示します。コレクションの要素にアクセスするには、インデックス指定方式を使用します:コレクション名(インデックス)。
コレクションメソッドは組み込みのストアドプロシージャであり、コレクションの情報を返したり、コレクションに対する操作を実行したりできます。コレクションを呼び出すには「.」を使用し、書式は「コレクション名 . メソッド名」となります。例えば、コレクション名 .COUNT メソッドは、そのコレクションの要素数を返すために使用されます。
注意
ソフトウェアパッケージのヘッダーで定義されたコレクションタイプは、同じ定義を持つローカルまたは独立したコレクションタイプと互換性がありません。
コレクションタイプとその違い
OceanBaseデータベースのPLは、以下の3種類のコレクションタイプをサポートしています:
関連配列(インデックステーブルとも呼ばれる)
変動配列(Varrays)
ネストテーブル
それぞれの類似点と相違点は以下の表に示されています。
| コレクションタイプ | 要素数 | インデックスタイプ | 密集または疎 | 未初期化状態 | 定義方法 |
|---|---|---|---|---|---|
| 関連配列 | 指定なし | 文字列または PLS_INTEGER |
いずれか一方 | 空 | PLブロックまたはパッケージ |
| 変動配列 | 指定 | Integer | 密集 | Null | スキーマレベル、PLブロックまたはパッケージ |
| ネストテーブル | 指定なし | Integer | 最初は密集、その後疎になる | Null | スキーマレベル、PLブロックまたはパッケージ |
要素数
要素数が指定されている場合、それはコレクション内の要素の最大数を意味します。要素数が指定されていない場合、コレクション内の最大要素数はインデックスタイプの上限となります。
密集または疎
密集コレクションとは、要素間に隙間がなく、最初の要素から最後の要素までの各要素が定義され、値を持つことを指します(ただし、その要素に
NOT NULL制約がある場合はこの値はNULLとなります)。疎コレクションとは、要素間に隙間があることを指します。初期化されていない状態
要素を一切含まない空のコレクションが存在します。空のコレクションに要素を追加するには、
EXTENDメソッドを呼び出してください。Nullコレクション(アトミックNullコレクションとも呼ばれる)は存在しません。Nullコレクションを有効なコレクションに変更するには、空の状態に初期化する必要があります。つまり、空に設定するか、NULL以外の値を割り当てる必要があります。EXTENDメソッドを使用してNullコレクションを初期化することはサポートされていません。定義方法
PLブロック内で定義されたコレクションタイプはローカルタイプです。これはブロック内でのみ利用可能であり、ブロックが独立したものまたはプログラムブロック内のサブプログラムに配置されている場合にのみ、コレクションはデータベースに保存されます。
パッケージヘッダー内で定義されたコレクションタイプはパブリックタイプです。パッケージ名(
package_name.type_name)を指定することで外部からの参照を実現できます。コレクションは、パッケージが削除されるまでデータベースに常に保存されます。スキーマレベルで定義されたコレクションタイプは独立タイプです。
CREATE TYPEステートメントを使用してコレクションを作成したり、DROP TYPEステートメントを使用して削除したりできます。
コレクション変数への代入
コレクション変数への代入は、以下の方法で行うことができます:
コンストラクタを呼び出してコレクションを作成し、それをコレクション変数に代入します。
代入文を使用して、既存のコレクション変数の値を代入します。
OUTまたはIN OUTパラメータとしてサブプログラムに渡し、その後サブプログラム内で代入します。
コレクション変数のスカラーエレメントに値を割り当てるには、collection_variable_name(index)を使用してそのエレメントを参照し、値を割り当てます。
コレクション変数に代入する際には、以下の点に注意する必要があります:
代入を行うためには、2つのコレクション変数が同時に同一の要素タイプを持っている必要があります。
配列またはネストテーブル変数には、
NULL値または同一データ型の空のコレクションを割り当てることができます。いずれの代入方法でも、変数は空値となります。ネストテーブル変数には、SQL
MULTISET演算またはSQLSET関数呼び出しの結果を割り当てることができます。
マルチディメンショナルコレクション
OceanBaseデータベースは、コレクションを使用してマルチディメンショナルコレクションを構築することをサポートしています。つまり、マルチディメンショナルコレクションの個々の要素はコレクションです。例えば、マルチディメンショナルコレクションは二次元配列(つまり配列の配列)になり得ます。
以下の例は、変動配列を持つ多次元配列です。
obclient> DECLARE
-- 最大容量が3で、要素型がINTの変動配列型type_var1を定義します
TYPE type_var1 IS VARRAY(3) OF INT;
-- 最大容量が5で、要素型がtype_var1の変動配列型type_var2を定義します
TYPE type_var2 IS VARRAY(5) OF type_var1;
-- type_var2型の変動配列変数varを定義します
var type_var2 := type_var2(type_var1(1,2,3), type_var1(4,5,6), type_var1(7,8,9));
BEGIN
FOR i IN 1..3 LOOP
FOR j IN 1..2 LOOP
DBMS_OUTPUT.PUT(VAR(i)(j) || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE('');
END LOOP;
END;/
Query OK, 0 rows affected
セットの比較
あるセット変数が別の変数より小さいかどうかを判断するには、まずその文脈における「小さい」という意味を定義し、TRUEまたはFALSEを返す関数を作成する必要があります。
関連付けられた配列変数はNULL値と比較できず、関連付けられた配列変数間でも比較できません。また、2つのセット変数を関係演算子を使用して比較することもできません。この制限は暗黙的な比較にも適用されます。例えば、セット変数はDISTINCT、GROUP BY、またはORDER BY句に含めることはできません。
セットの比較には主に以下の3つの典型的なケースがあります:
変動配列とネストテーブル変数と
NULL値の比較NULL値と比較する場合は、IS [NOT] NULL演算子を使用してください。等号(=)や不等号(<>、!=、〜=、または^=)などの関係演算子は使用できません。例:
obclient> DECLARE TYPE players IS VARRAY(5) OF VARCHAR2(20); -- 変動配列型を定義 names PLAYERS := players('Charles', 'Carl', 'James'); -- 変動配列変数を定義 TYPE register IS TABLE OF VARCHAR2(20); -- ネストテーブル型を定義 team REGISTER; -- ネストテーブル変数を定義 BEGIN IF names IS NULL THEN DBMS_OUTPUT.PUT_LINE('Names IS NULL'); ELSE DBMS_OUTPUT.PUT_LINE('Names IS NOT NULL'); END IF; IF team IS NOT NULL THEN DBMS_OUTPUT.PUT_LINE('Team IS NOT NULL'); ELSE DBMS_OUTPUT.PUT_LINE('Team IS NULL'); END IF; END; / Query OK, 0 rows affected Names IS NOT NULL Team IS NULLネストテーブルの同一性の比較
2つのネストテーブル変数が等しいとは、両者が同じ要素集合(任意の順序で)を持つ場合に限ります。2つのネストテーブル変数が同じネストテーブル型を持ち、かつそのネストテーブル型がレコード型の要素を持たない場合、関係演算子である等号(=)や不等号(< >、!=、〜=、または^=)を使用して比較できます。
例:
obclient> DECLARE TYPE players IS TABLE OF VARCHAR2(30); -- 要素型が集合型ではない name_list1 PLAYERS := players('Andrew', 'Barton', 'Conrad', 'Dick','Edward'); name_list2 PLAYERS := players('Dick', 'Edward', 'Andrew', 'Conrad','Barton'); name_list3 PLAYERS := players('John', 'Mary', 'Alberto', 'Juanita'); BEGIN IF name_list1 = name_list2 THEN DBMS_OUTPUT.PUT_LINE('name_list1 = name_list2'); END IF; IF name_list2 != name_list3 THEN DBMS_OUTPUT.PUT_LINE('name_list2 != name_list3'); END IF; END; / Query OK, 0 rows affected name_list1 = name_list2 name_list2 != name_list3ネストテーブルとSQL集合式の比較
SQL集合式を使用してネストテーブル変数を比較し、特定のプロパティをテストできます。例:
obclient> DECLARE TYPE nested_ty IS TABLE OF NUMBER; t1 nested_ty := nested_ty(6,7,9); t2 nested_ty := nested_ty(8,7,6); t3 nested_ty := nested_ty(7,8,6,8); t4 nested_ty := nested_ty(6,7,8); t5 nested_ty := nested_ty(6,7,8,6,7); PROCEDURE obtest ( result BOOLEAN := NULL, quantity NUMBER := NULL ) IS BEGIN IF result IS NOT NULL THEN DBMS_OUTPUT.PUT_LINE ( CASE result WHEN TRUE THEN 'True' WHEN FALSE THEN 'False' END ); END IF; IF quantity IS NOT NULL THEN DBMS_OUTPUT.PUT_LINE(quantity); END IF; END; BEGIN obtest(result => (t4 IN (t1,t2,t3,t5))); -- 条件 obtest(result => (t4 SUBMULTISET OF t3)); -- 条件 obtest(result => (t4 NOT SUBMULTISET OF t1)); -- 条件 obtest(result => (4 MEMBER OF t4)); -- 条件 obtest(result => (t1 IS A SET)); -- 条件 obtest(result => (t1 IS NOT A SET)); -- 条件 obtest(result => (t5 IS EMPTY)); -- 条件 obtest(quantity => (CARDINALITY(t5))); -- 関数 obtest(quantity => (CARDINALITY(SET(t5)))); -- 2つの関数 END; / Query OK, 0 rows affected True True True False True False False 5 3