Oracle PL/SQLコレクション: VARRAY、ネスト、表による索引付け

⚡ スマートサマリー

PL/SQLコレクションは、同じデータ型の要素を順序付けしてグループ化したもので、各要素には添え字でアクセスできます。Varray、ネストされたテーブル、インデックス付きテーブルの3種類があり、サイズが固定されているかどうか、添え字の動作方法、データベースに格納できるかどうかが異なります。

  • 🧺 定義: コレクションには、同じ種類の要素が多数含まれており、それぞれの要素は固有の添え字によって識別されます。
  • 📐 ヴァレイ: 上限サイズは固定、常に密、数値添え字、使用前に初期化が必要。
  • 📚 ネストされたテーブル: サイズ制限はなく、密でも疎でも構わず、システムテーブルに格納でき、EXTEND で拡張できます。
  • 🔑 テーブル別索引: サイズ制限はありません。添え字は文字列または負の整数にすることができ、データベースには保存されません。
  • 🏗️ コンストラクタ: Varrayとネストされたテーブルは、参照する前に明示的なコンストラクタで初期化する必要があります。
  • 🛠️ メソッド: COUNT、EXISTS、FIRST、LAST、EXTEND、TRIM、DELETE はコレクションを管理します。
  • ⚡ バルク: BULK COLLECTは、処理を迅速化するために、コレクションを一度に作成します。

Oracle PL/SQLコレクション

コレクションとは何ですか?

コレクションとは、特定のデータ型の要素を順序付けしてまとめたものです。コレクションは、単純なデータ型のコレクションである場合もあれば、ユーザー定義型やレコード型などの複雑なデータ型のコレクションである場合もあります。

コレクションでは、各要素は、 "添字。" 各項目には固有の添え字が割り当てられ、その固有の添え字を参照することでデータを操作したり取得したりすることができる。

コレクションは、同じタイプの大量のデータを処理または操作する必要がある場合に最も役立ちます。コレクションは、「BULK」オプションを使用して全体としてデータを格納および操作できます。 Oracle.

コレクションは、以下に示すように、構造、添え字、および格納方法に基づいて分類されます。

  • インデックス付きテーブル(連想配列とも呼ばれる)
  • ネストされたテーブル
  • 変数

コレクション内のデータは、いつでもコレクション名、添え字、フィールド名または列名の 3 つの用語で参照できます。 ( )これらのコレクションカテゴリについては、以下のセクションで説明します。

コレクションの種類の概要

これら3種類のコレクションタイプは、それぞれ異なるトレードオフを持っています。以下の表では、それぞれのタイプを並べて比較した後、詳細に解説します。

側面 ヴァレイ ネストされたテーブル 表による索引
サイズ 固定上限値 制限なし 制限なし
添字 数値の 数値の 整数または文字列
密度 常に密度が高い 密集しているか疎らか 常にまばら
データベースに保存されています はい はい いいえ
初期化が必要です はい はい いいえ

変数

Varrayは、配列のサイズが固定されており、それを超えることができないコレクションです。Varrayの添え字は数値です。Varrayの属性は次のとおりです。

  • 上限サイズは固定されています。
  • 添え字「1」から順にデータが格納されます。
  • このコレクション型は常に密な配列であり、個々の配列要素を削除することはできません。Varrayは全体として削除するか、末尾から一部を削除することができます。
  • 常に密度が高いため、柔軟性が非常に低い。
  • 配列のサイズが既知であり、すべての要素に対して同様の処理が行われる場合に、この方法はより適切です。
  • コレクションの添え字と要素数は常に安定している。
  • 使用する前に初期化する必要があります。初期化されていないコレクションに対して、EXISTS以外の操作を行うとエラーが発生します。
  • これは、データベース全体で参照可能なデータベースオブジェクトとして作成することも、サブルーチン内でのみ使用されるように作成することもできます。

下の図は、Varray(密配列)のメモリ割り当てについて説明しています。

添字 1 2 3 4 5 6 7
値 Xyz Dfv スデ Cxs Vbc ヌー クウェ

VARRAY の構文:

TYPE <type_name> IS VARRAY (<SIZE>) OF <DATA_TYPE>;
  • 上記の構文では、type_name は指定されたサイズ制限内で 'DATA_TYPE' 型の VARRAY として宣言されています。データ型は単純型でも複雑型でも構いません。

ネストされたテーブル

ネストされたテーブルは、配列のサイズが固定されていないコレクションです。数値の添え字型を持ちます。ネストされたテーブル型の詳細については、以下をご覧ください。

  • ネストされたテーブルには、サイズの上限はありません。
  • 上限が固定されていないため、メモリを使用するたびに「EXTEND」キーワードを使用してメモリを拡張する必要があります。
  • 添え字「1」から順にデータが格納されます。
  • このコレクションタイプは 密でまばら; 密なデータとして作成することも、個々の要素をランダムに削除して疎なデータにすることもできます。
  • 配列要素の削除において、より柔軟な対応が可能になります。
  • これはシステムによって生成されたデータベーステーブルに格納され、SELECTクエリで値を取得するために使用できます。
  • 添え字と桁数は異なる場合があります。
  • 使用する前に初期化する必要があります。初期化されていないコレクションに対して、EXISTS以外の操作を行うとエラーが発生します。
  • これは、データベース全体で参照可能なデータベースオブジェクトとして作成することも、サブルーチン内でのみ使用されるように作成することもできます。

下図は、ネストされたテーブル(密なテーブルと疎なテーブル)のメモリ割り当てについて説明しています。空の要素スペースは疎な要素を表します。

添字 1 2 3 4 5 6 7
値 (密) Xyz Dfv スデ Cxs Vbc ヌー クウェ
値(疎行列) クウェ ASD AFG ASD WER

ネストしたテーブルの構文:

TYPE <type_name> IS TABLE OF <DATA_TYPE>;
  • 上記の構文では、type_name は型 'DATA_TYPE' のネストされたテーブルコレクションとして宣言されています。データ型は、単純型でも複合型でも構いません。

表による索引

インデックス付きテーブルは、配列サイズが固定されていないコレクションです。他のコレクションタイプとは異なり、インデックス付きテーブルの添え字はユーザーが定義できます。インデックス付きテーブルの属性は次のとおりです。

  • 添え字は整数または文字列を指定できます。コレクションを作成する際に、添え字の型を指定する必要があります。
  • これらのコレクションは順番に保存されません。
  • それらは常に本質的にまばらです。
  • 配列のサイズは固定されていません。
  • これらはデータベースの列に保存することはできません。特定のセッション内で作成され、使用されます。
  • それらは添え字を維持する上でより柔軟性を提供する。
  • 添え字は負の数列でも構いません。
  • これらは、同じサブプログラム内で使用される比較的小さなコレクション値に適しています。
  • 使用前に初期化する必要はありません。
  • これらはデータベースオブジェクトとして作成することはできません。サブルーチン内でのみ作成されます。
  • このコレクションタイプでは、各レコードに添え字を明示的に指定する必要があるため、BULK COLLECTは使用できません。

下図は、インデックス付きテーブル(疎行列)のメモリ割り当てについて説明しています。空の要素スペースは、疎行列要素を表します。

添字(varchar) 最初 SECOND THIRD 第4 FIFTH SIXTH XNUMX番目
値(疎行列) クウェ ASD AFG ASD WER

テーブルによるインデックスの構文:

TYPE <type_name> IS TABLE OF <DATA_TYPE> INDEX BY VARCHAR2 (10);
  • 上記の構文では、type_nameは型「DATA_TYPE」のインデックス付きテーブルコレクションとして宣言されています。添え字変数は、最大サイズ10のVARCHAR2型として指定されています。

コレクションのコンストラクターと初期化の概念

コンストラクタは、によって提供される組み込み関数です。 Oracle オブジェクトまたはコレクションと同じ名前を持つコンストラクタ。セッション内でオブジェクトまたはコレクションが初めて参照されるたびに、最初に実行されます。コレクションコンテキストにおけるコンストラクタの重要な詳細:

  • コレクションの場合、コレクションを初期化するには、これらのコンストラクタを明示的に呼び出す必要があります。
  • Varrayとネストされたテーブルはどちらも、プログラム内で参照する前に、これらのコンストラクタを使用して初期化する必要があります。
  • コンストラクタは、コレクション(Varrayを除く)のメモリ割り当てを暗黙的に拡張するため、コレクションに変数を割り当てることもできます。
  • コンストラクタを介して値を割り当てると、コレクションが疎になることはありません。

収集方法

Oracle コレクションを操作・管理するための多くの関数を提供します。これらの関数は、コレクションのさまざまな属性を決定および変更します。以下の表に、各関数とその説明を示します。

方法 詳細説明 構文
存在します (n) ブール値を返します。n番目の要素が存在する場合はTRUE、存在しない場合はFALSEを返します。初期化されていないコレクションに対しては、EXISTSのみを使用できます。 .EXISTS(要素の位置)
COUNT コレクションに含まれる要素の総数を返します。 。カウント
LIMIT コレクションの最大サイズを返します。Varray の場合は固定サイズを返し、ネストされたテーブルおよびインデックス付きテーブルの場合は NULL を返します。 .LIMIT
最初 コレクションの最初の添え字の値を返します。 。初め
LAST コレクションの最後の添え字の値を返します。 。最後
前 (n) n番目の要素の直前の添え字を返します。添え字がない場合はNULLを返します。 .PRIOR(n)
次へ (n) n番目の要素の次の添え字を返します。添え字がない場合はNULLを返します。 .NEXT(n)
延長 コレクションの末尾にある要素を1つ拡張します。 。伸ばす
拡張 (n) コレクションの末尾にn個の要素を追加します。 .EXTEND(n)
拡張 (n,i) コレクションの末尾にあるi番目の要素のn個のコピーを拡張します。 .EXTEND(n,i)
TRIM コレクションの末尾から要素を1つ削除します。 。トリム
トリム (n) コレクションの末尾からn個の要素を削除します。 .TRIM(n)
DELETE コレクションからすべての要素を削除し、コレクションを空にします。 。消去
削除 (n) n番目の要素を削除します。n番目の要素がNULLの場合は、何も行いません。 .DELETE(n)
削除 (m,n) コレクション内のm番目からn番目までの範囲の要素を削除します。 .DELETE(m,n)

例1:サブプログラムレベルでのレコードタイプ

この例では、' を使用してコレクションにデータを入力する方法を示します。一括収集そして、収集データを参照する方法。

BULK COLLECTを使用してデータが格納されたPL/SQLコレクションの例

DECLARE
TYPE emp_det IS RECORD
(
EMP_NO NUMBER,
EMP_NAME VARCHAR2(150),
MANAGER NUMBER,
SALARY NUMBER
);
TYPE emp_det_tbl IS TABLE OF emp_det;
guru99_emp_rec emp_det_tbl:= emp_det_tbl();
BEGIN
INSERT INTO emp (emp_no,emp_name, salary, manager) VALUES (1000,'AAA',25000,1000);
INSERT INTO emp (emp_no,emp_name, salary, manager) VALUES (1001,'XXX',10000,1000);
INSERT INTO emp (emp_no, emp_name, salary, manager) VALUES (1002,'YYY',15000,1000);
INSERT INTO emp (emp_no,emp_name,salary, manager) VALUES (1003,'ZZZ',7500,1000);
COMMIT;
SELECT emp_no,emp_name,manager,salary BULK COLLECT INTO guru99_emp_rec
FROM emp;
dbms_output.put_line ('Employee Detail');
FOR i IN guru99_emp_rec.FIRST..guru99_emp_rec.LAST
LOOP
dbms_output.put_line ('Employee Number: '||guru99_emp_rec(i).emp_no);
dbms_output.put_line ('Employee Name: '||guru99_emp_rec(i).emp_name);
dbms_output.put_line ('Employee Salary:'|| guru99_emp_rec(i).salary);
dbms_output.put_line('Employee Manager Number:'||guru99_emp_rec(i).manager);
dbms_output.put_line('--------------------------------');
END LOOP;
END;
/

Code 説明

  • Code 2行目~8行目: レコードタイプ 'emp_det' は、データ型が NUMBER、VARCHAR2、NUMBER、および NUMBER である emp_no、emp_name、manager、および salary の列で宣言されています。
  • Code 9行目: レコードタイプ要素「emp_det」のコレクション「emp_det_tbl」を作成しています。
  • Code 10行目: 変数「guru99_emp_rec」を「emp_det_tbl」型として宣言し、nullコンストラクタで初期化します。
  • Code 12行目~15行目: サンプル データを 'emp' テーブルに挿入します。
  • Code 16行目: 挿入トランザクションをコミットしています。
  • Code 17行目: 「emp」テーブルからレコードを取得し、「BULK COLLECT」を使用してコレクション変数に一括でデータを格納します。これで、変数「guru99_emp_rec」には、「emp」テーブルに存在するすべてのレコードが格納されました。
  • Code 19行目~26行目: 'FOR' ループを設定して、コレクション内のすべてのレコードを 1 つずつ出力します。コレクション メソッド FIRST と LAST は、コレクションの下限と上限として使用されます。 ループ.

出力: 上記のコードを実行すると、以下の出力が得られます。

Employee Detail
Employee Number: 1000
Employee Name: AAA
Employee Salary: 25000
Employee Manager Number: 1000
----------------------------------------------
Employee Number: 1001
Employee Name: XXX
Employee Salary: 10000
Employee Manager Number: 1000
----------------------------------------------
Employee Number: 1002
Employee Name: YYY
Employee Salary: 15000
Employee Manager Number: 1000
----------------------------------------------
Employee Number: 1003
Employee Name: ZZZ
Employee Salary: 7500
Employee Manager Number: 1000
----------------------------------------------

よくあるご質問

Varrayは上限サイズが固定されており、常に密な構造になります。一方、ネストされたテーブルはサイズ制限がなく、疎な構造にすることも、拡張することも可能です。そのため、データ量の増加や欠落データの処理において、より柔軟に対応できます。

これはメモリ上の連想配列であり、格納されたテーブルではないためです。添え字は検索キーとして機能するため、文字列や負の整数も使用できます。これは、セッション内でのキーによる検索に便利です。

初期化されていないVarrayまたはネストされたテーブルは、アトミックにnullであるため、要素を参照するとエラーが発生します。コンストラクタを呼び出すとそれが割り当てられ、その後、EXTENDや代入によってデータを追加できます。

はい。サイズが固定されているか、データが保存されているか、文字列キーが必要かといった条件に基づいて、AIはVarray、ネストされたテーブル、またはインデックス付きテーブルを指し示し、それぞれのトレードオフを説明することができます。

BULK COLLECTは、SQLエンジンとPL/SQLエンジン間の単一のコンテキストスイッチで全ての行をコレクションにロードします。行ごとに1回のスイッチを行うのではなく、この操作を行うことで、大規模な結果セットにおけるオーバーヘッドを大幅に削減できます。