Plsql-collections

提供:Dev Guides
移動先:案内検索

PL/SQL-コレクション

この章では、PL/SQLのコレクションについて説明します。 コレクションは、同じデータ型を持つ要素の順序付けられたグループです。 各要素は、コレクション内での位置を表す一意の添え字によって識別されます。

PL/SQLは3つのコレクションタイプを提供します-

  • インデックスバイテーブルまたは連想配列
  • 入れ子になったテーブル
  • 可変サイズの配列またはVarray

Oracleのドキュメントは、コレクションの種類ごとに次の特性を提供します-

Collection Type Number of Elements Subscript Type Dense or Sparse Where Created Can Be Object Type Attribute
Associative array (or index-by table) Unbounded String or integer Either Only in PL/SQL block No
Nested table Unbounded Integer Starts dense, can become sparse Either in PL/SQL block or at schema level Yes
Variablesize array (Varray) Bounded Integer Always dense Either in PL/SQL block or at schema level Yes
*'PL/SQL配列'* の章でVARRAYについて既に説明しました。 この章では、PL/SQL表について説明します。

両方のタイプのPL/SQL表、つまり、索引付き表とネストした表は同じ構造を持ち、行は添字表記を使用してアクセスされます。 ただし、これら2つのタイプのテーブルは1つの側面が異なります。ネストした表はデータベース列に格納できますが、索引付き表は格納できません。

インデックステーブル

*index-by* テーブル(*連想配列*とも呼ばれる)は、*キーと値*のペアのセットです。 各キーは一意であり、対応する値を見つけるために使用されます。 キーは整数または文字列のいずれかです。

インデックス付きテーブルは、次の構文を使用して作成されます。 ここでは、 table_name という名前の index-by テーブルを作成しています。そのキーはsubscript_typeであり、関連する値は_element_type_です

TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY subscript_type;

table_name type_name;

次の例は、名前とともに整数値を保存するテーブルを作成し、後で同じ名前のリストを出力する方法を示しています。

DECLARE
   TYPE salary IS TABLE OF NUMBER INDEX BY VARCHAR2(20);
   salary_list salary;
   name   VARCHAR2(20);
BEGIN
   -- adding elements to the table
   salary_list('Rajnish') := 62000;
   salary_list('Minakshi') := 75000;
   salary_list('Martin') := 100000;
   salary_list('James') := 78000;

   -- printing the table
   name := salary_list.FIRST;
   WHILE name IS NOT null LOOP
      dbms_output.put_line
      ('Salary of ' || name || ' is ' || TO_CHAR(salary_list(name)));
      name := salary_list.NEXT(name);
   END LOOP;
END;
/

上記のコードがSQLプロンプトで実行されると、次の結果が生成されます-

Salary of James is 78000
Salary of Martin is 100000
Salary of Minakshi is 75000
Salary of Rajnish is 62000

PL/SQL procedure successfully completed.

インデックス付きテーブルの要素は、任意のデータベーステーブルの*%ROWTYPE または任意のデータベーステーブルフィールドの%TYPE にすることもできます。 次の例は、概念を示しています。 データベースに保存されている *CUSTOMERS テーブルを次のように使用します-

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |
|  2 | Khilan   |  25 | Delhi     |  1500.00 |
|  3 | kaushik  |  23 | Kota      |  2000.00 |
|  4 | Chaitali |  25 | Mumbai    |  6500.00 |
|  5 | Hardik   |  27 | Bhopal    |  8500.00 |
|  6 | Komal    |  22 | MP        |  4500.00 |
+----+----------+-----+-----------+----------+
DECLARE
   CURSOR c_customers is
      select name from customers;

   TYPE c_list IS TABLE of customers.Name%type INDEX BY binary_integer;
   name_list c_list;
   counter integer :=0;
BEGIN
   FOR n IN c_customers LOOP
      counter := counter +1;
      name_list(counter) := n.name;
      dbms_output.put_line('Customer('||counter||'):'||name_lis t(counter));
   END LOOP;
END;
/

上記のコードがSQLプロンプトで実行されると、次の結果が生成されます-

Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal

PL/SQL procedure successfully completed

入れ子になったテーブル

  • ネストされたテーブル*は、任意の数の要素を持つ1次元配列のようなものです。 ただし、ネストされたテーブルは、次の点で配列とは異なります-
  • 配列には宣言された数の要素がありますが、ネストされたテーブルにはありません。 ネストした表のサイズは動的に増加する場合があります。
  • 配列は常に密です。つまり、常に連続した添え字を持っています。 ネストされた配列は最初は密ですが、要素が削除されると疎になる可能性があります。

ネストされたテーブルは、次の構文を使用して作成されます-

TYPE type_name IS TABLE OF element_type [NOT NULL];

table_name type_name;

この宣言は index-by テーブルの宣言に似ていますが、 INDEX BY 句はありません。

ネストした表は、データベース列に格納できます。 さらに、単一列のテーブルをより大きなテーブルに結合するSQL操作を簡素化するために使用できます。 連想配列はデータベースに保存できません。

次の例は、ネストされたテーブルの使用を示しています-

DECLARE
   TYPE names_table IS TABLE OF VARCHAR2(10);
   TYPE grades IS TABLE OF INTEGER;
   names names_table;
   marks grades;
   total integer;
BEGIN
   names := names_table('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz');
   marks:= grades(98, 97, 78, 87, 92);
   total := names.count;
   dbms_output.put_line('Total '|| total || ' Students');
   FOR i IN 1 .. total LOOP
      dbms_output.put_line('Student:'||names(i)||', Marks:' || marks(i));
   end loop;
END;
/

上記のコードがSQLプロンプトで実行されると、次の結果が生成されます-

Total 5 Students
Student:Kavita, Marks:98
Student:Pritam, Marks:97
Student:Ayan, Marks:78
Student:Rishav, Marks:87
Student:Aziz, Marks:92

PL/SQL procedure successfully completed.

ネストされたテーブル*の要素は、データベーステーブルの%ROWTYPE *またはデータベーステーブルフィールドの%TYPEでもあります。 次の例は、概念を示しています。 データベースに保存されているCUSTOMERSテーブルを次のように使用します-

Select *from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |
|  2 | Khilan   |  25 | Delhi     |  1500.00 |
|  3 | kaushik  |  23 | Kota      |  2000.00 |
|  4 | Chaitali |  25 | Mumbai    |  6500.00 |
|  5 | Hardik   |  27 | Bhopal    |  8500.00 |
|  6 | Komal    |  22 | MP        |  4500.00 |
+----+----------+-----+-----------+----------+
DECLARE
   CURSOR c_customers is
      SELECT  name FROM customers;
   TYPE c_list IS TABLE of customerS.No.ame%type;
   name_list c_list := c_list();
   counter integer :=0;
BEGIN
   FOR n IN c_customers LOOP
      counter := counter +1;
      name_list.extend;
      name_list(counter)  := n.name;
      dbms_output.put_line('Customer('||counter||'):'||name_list(counter));
   END LOOP;
END;
/

上記のコードがSQLプロンプトで実行されると、次の結果が生成されます-

Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal

PL/SQL procedure successfully completed.

収集方法

PL/SQLは、コレクションを使いやすくする組み込みのコレクションメソッドを提供します。 次の表は、メソッドとその目的を示しています-

S.No Method Name & Purpose
1
  • EXISTS(n)*

コレクション内のn番目の要素が存在する場合、TRUEを返します。そうでない場合はFALSEを返します。

2

COUNT

コレクションに現在含まれている要素の数を返します。

3

LIMIT

コレクションの最大サイズを確認します。

4

FIRST

整数の添字を使用するコレクション内の最初の(最小の)インデックス番号を返します。

5

LAST

整数の添え字を使用するコレクション内の最後の(最大の)インデックス番号を返します。

6

PRIOR(n)

コレクション内のインデックスnの前にあるインデックス番号を返します。

7

NEXT(n)

インデックスnに続くインデックス番号を返します。

8

EXTEND

1つのnull要素をコレクションに追加します。

9

EXTEND(n)

コレクションにn個のnull要素を追加します。

10

EXTEND(n,i)

i ^ th ^要素の n コピーをコレクションに追加します。

11

TRIM

コレクションの末尾から1つの要素を削除します。

12

TRIM(n)

コレクションの末尾から n 個の要素を削除します。

13

DELETE

COUNTを0に設定して、コレクションからすべての要素を削除します。

14

DELETE(n)

数値キーまたはネストされたテーブルを使用して、連想配列から n ^ th ^ 要素を削除します。 連想配列に文字列キーがある場合、キー値に対応する要素が削除されます。 n がヌルの場合、* DELETE(n)*は何もしません。

15

DELETE(m,n)

連想配列またはネストされたテーブルから m..n の範囲のすべての要素を削除します。 mn よりも大きい場合、または m または n がヌルの場合、* DELETE(m、n)*は何もしません。

コレクションの例外

次の表は、コレクションの例外とそれらが発生した場合を提供します-

Collection Exception Raised in Situations
COLLECTION_IS_NULL You try to operate on an atomically null collection.
NO_DATA_FOUND A subscript designates an element that was deleted, or a nonexistent element of an associative array.
SUBSCRIPT_BEYOND_COUNT A subscript exceeds the number of elements in a collection.
SUBSCRIPT_OUTSIDE_LIMIT A subscript is outside the allowed range.
VALUE_ERROR A subscript is null or not convertible to the key type. This exception might occur if the key is defined as a PLS_INTEGER range, and the subscript is outside this range.