5.1 コレクション・データ型

Oracleでは、VARRAYとネストした表のコレクション・データ型がサポートされます。

  • VARRAYとは、順序付けられた要素の集合です。

  • ネストした表には、要素をいくつでも入れることができます。順序付けはされません。

一定数の項目のみ格納する必要がある場合、順序に従って要素をループする必要がある場合、またはコレクション全体を1つの値として取り出して操作する必要がある場合は、VARRAYを使用してください。

コレクションについての問合せを効率的に実行する必要がある場合は、任意の数の要素を扱うか、大量の挿入、更新または削除を行ってから、ネストした表を使用してください。

内容は次のとおりです。

関連項目:

ネストした表の使用の詳細は、コレクションの設計上の考慮点を参照してください。

5.1.1 コレクション型の作成

CREATE TYPEおよびCREATE TYPE BODYを使用して、ネストした表型を作成します。

例5-1では、person_typオブジェクトと、person_typオブジェクトのネストした表型としてのpeople_typを作成します。どちらも、他の例で使用します。

例5-1 後続の例で使用するCREATE TYPE person_typ

CREATE TYPE person_typ AS OBJECT (
  idno           NUMBER,
  name           VARCHAR2(30),
  phone          VARCHAR2(20),
  MAP MEMBER FUNCTION get_idno RETURN NUMBER, 
  MEMBER PROCEDURE display_details ( SELF IN OUT NOCOPY person_typ ) );
/

CREATE TYPE BODY person_typ AS
  MAP MEMBER FUNCTION get_idno RETURN NUMBER IS
  BEGIN
    RETURN idno;
  END;
  MEMBER PROCEDURE display_details ( SELF IN OUT NOCOPY person_typ ) IS
  BEGIN
    -- use the put_line procedure of the DBMS_OUTPUT package to display details
    DBMS_OUTPUT.put_line(TO_CHAR(idno) || ' - '  || name || ' - '  || phone);
  END;
END;
/

CREATE TYPE people_typ AS TABLE OF person_typ; -- nested table type
/

5.1.2 VARRAYまたはネストした表のインスタンスの作成

コレクション型のインスタンスは、他のオブジェクト型のインスタンスを作成する場合と同じ方法で、型のコンストラクタ・メソッドをコールして作成します。

コンストラクタ・メソッドの名前は、型の名前です。コレクションの各要素は、カンマで区切ったメソッドの引数のリストとして指定します。次に例を示します。

( person_typ(1, 'John Smith', '1-650-555-0135'),

空のリストでコンストラクタ・メソッドをコールすると、その型の空のコレクションが作成されます。空のコレクションとは、偶然に空になっている実際のコレクションで、NULLコレクションとは異なる点に注意してください。ネストした表の使用方法の詳細は、「ネストした表の設計上の考慮点」を参照してください。

5.1.3 ネストした表に値を挿入するためのコンストラクタ・メソッドの使用

SQL文のコンストラクタ・メソッドを使用して、ネストした表に値を挿入できます。

例5-2では、最初にネストした表型people_typのインスタンスが含まれる表(people_column)を作成し、次にSQL文でコンストラクタ・メソッドを使用して値をpeople_typに挿入する方法を示します。この例では、コンストラクタ・メソッドのリテラル起動を使用します。

例5-2 ネストした表に値を挿入するためのコンストラクタ・メソッドの使用

-- Requires Ex. 5-1
CREATE TABLE people_tab (
    group_no NUMBER,
    people_column people_typ )  -- an instance of nested table
    NESTED TABLE people_column STORE AS people_column_nt; -- storage table for NT
INSERT INTO people_tab VALUES (
            100,
            people_typ( person_typ(1, 'John Smith', '1-650-555-0135'),
                        person_typ(2, 'Diane Smith', NULL)));

5.1.4 デフォルトを指定するためのコンストラクタのリテラル起動

表の列をオブジェクト型またはコレクション型として宣言する場合、DEFAULT句を含めることができます。

明示的に列に値を指定しない場合には、このDEFAULT句で指定した値が使用されます。

DEFAULT句には、そのオブジェクトまたはコレクションのコンストラクタ・メソッドのリテラル起動を含める必要があります。

例5-3に、コンストラクタ・メソッドのリテラル起動を使用してオブジェクトperson_typおよびネストした表people_typのデフォルトを指定する方法を示します。

例5-3 デフォルトを指定するためのコンストラクタ・メソッドのリテラル起動の使用

-- requires Ex. 5-1
CREATE TABLE department_persons (
  dept_no    NUMBER PRIMARY KEY,
  dept_name  CHAR(20),
  dept_mgr   person_typ DEFAULT person_typ(10,'John Doe',NULL),
  dept_emps  people_typ DEFAULT people_typ() ) -- instance of nested table type
  NESTED TABLE dept_emps STORE AS dept_emps_tab;

INSERT INTO department_persons VALUES 
   ( 101, 'Physical Sciences', person_typ(65,'Vrinda Mills', '1-650-555-0125'),
           people_typ( person_typ(1, 'John Smith', '1-650-555-0135'), 
                        person_typ(2, 'Diane Smith', NULL) ) );
INSERT INTO department_persons VALUES 
  ( 104, 'Life Sciences', person_typ(70,'James Hall', '1-415-555-0101'), 
    people_typ() ); -- an empty people_typ table

people_typ()は、空のネストした表people_typのコンストラクタ・メソッドのリテラル起動であることに注意してください。

例5-16および例5-17に示すように、department_persons表は2つの方法で問い合せることができます。

5.1.5 VARRAYについて

VARRAYとは、順序付けられたデータ要素の集合です。任意のVARRAYのすべての要素は、同じデータ型または宣言されたデータ型のサブタイプの要素です。各要素は、索引を持ちますが、これは配列における要素の位置に対応する番号です。索引番号は、特定の要素にアクセスするために使用されます。

VARRAYを定義するときは、ここに格納できる要素の最大数を指定しますが、この値は後で変更できます。配列内の要素数は、その配列のサイズを表します。

次の文では、それぞれがVARCHAR2(80)データ型の最大10個の要素を持つ配列型email_list_arrを作成します。

CREATE TYPE email_list_arr AS VARRAY(10) OF VARCHAR2(80);
/

5.1.6 VARRAYの作成と移入

配列型を作成しても、SQLオブジェクト型と同様、領域は割り当てらません。

データ型が定義され、その用途は次のとおりです。

  • リレーショナル表の列のデータ型。

  • オブジェクト型属性。

  • PL/SQL変数、パラメータまたはファンクション戻り値の型。

例5-4では、オブジェクト型の配列としてのVARRAY型を作成します。phone_varray_typ VARRAY型は、dept_phone_list表の列のデータ型として使用されます。このINSERT文は、VARRAY phone_varray_typとオブジェクトphone_typのコンストラクタを起動してphone_varray_typに値を挿入する方法を示しています。

PL/SQLまたはビュー問合せなど、手順上の目的でXMLTypeVARRAY型またはLOB型を作成できます。ただし、これらの型のVARRAYのデータベース記憶域はサポートされていません。このため、XMLTypeのVARRAY型またはLOB型のオブジェクト表またはオブジェクト型列は作成できません。

例5-4 VARRAYデータ型の作成と移入

CREATE TYPE phone_typ AS OBJECT (
    country_code   VARCHAR2(2), 
    area_code      VARCHAR2(3),
    ph_number      VARCHAR2(7));
/
CREATE TYPE phone_varray_typ AS VARRAY(5) OF phone_typ;
/
CREATE TABLE dept_phone_list (
  dept_no NUMBER(5), 
  phone_list phone_varray_typ);

INSERT INTO dept_phone_list VALUES (
   100,
   phone_varray_typ( phone_typ ('01', '650', '5550123'),
                      phone_typ ('01', '650', '5550148'),
                      phone_typ ('01', '650', '5550192')));

通常、VARRAYはインラインに、つまり、その行にある他のデータと同じ表領域に格納されます。サイズが十分であれば、BLOBとして格納されます。

関連項目:

5.1.7 ネストした表

ネストした表は順序を設定していないデータ要素のセットで、すべて同じデータ型です。表の定義に最大値の指定はなく、要素の順序は維持されません。通常の表を扱う場合と同様に、TABLE式を使用して、ネストした表でも選択、挿入、削除および更新を行います。

ネストした表は単一列として表示できます。ネストした表の列がオブジェクト型であれば、オブジェクト型の各属性に対して列を持つ複数列表としても、表を表示できます。

内容は次のとおりです。

5.1.7.1 ネストした表の作成

ネストした表型を作成するには、CREATE TYPE ... AS TABLE OF文を使用します。次に例を示します。

CREATE TYPE people_typ AS TABLE OF person_typ; 

表型の定義では、領域は割り当てられません。ここでは次のような型を定義します。

  • リレーショナル表の列のデータ型。

  • オブジェクト型属性。

  • PL/SQL変数、パラメータまたはファンクション戻り型。

5.1.7.2 ネストした表の要素の格納

ネストした表の要素は、実際には個別の記憶表に格納されます。

Oracleでは、ネストした表のデータは、リレーショナル表の列またはオブジェクト表の属性である両方のネストした表型に対応するオブジェクト表に関連付けられた1つの記憶表に格納されます。この記憶表には、ネストした表の各要素が属する親表の行やオブジェクトを識別する列が含まれています。図9-2を参照してください。

NESTED TABLE..STORE AS句は、ネストした表の記憶域名を指定します。記憶域名は、ネストした表に索引を作成するときに使用します。

例5-5では、ネストした表を作成して移入し、例5-1で定義したオブジェクトperson_typおよびネストした表people_typを使用して、ネストした表記憶域を指定します。

例5-5 単純なネストした表の作成および移入

-- Requires 5-1
CREATE TABLE students (
   graduation DATE, 
   math_majors people_typ, -- nested tables (empty)
   chem_majors people_typ, 
   physics_majors people_typ)
  NESTED TABLE math_majors STORE AS math_majors_nt  -- storage tables
  NESTED TABLE chem_majors STORE AS chem_majors_nt
  NESTED TABLE physics_majors STORE AS physics_majors_nt;

CREATE INDEX math_idno_idx ON math_majors_nt(idno);
CREATE INDEX chem_idno_idx ON chem_majors_nt(idno);
CREATE INDEX physics_idno_idx ON physics_majors_nt(idno);

INSERT INTO students (graduation) VALUES ('01-JUN-03');
UPDATE students
  SET math_majors = 
        people_typ (person_typ(12, 'Bob Jones', '650-555-0130'), 
                    person_typ(31, 'Sarah Chen', '415-555-0120'),
                    person_typ(45, 'Chris Woods', '415-555-0124')),
      chem_majors = 
        people_typ (person_typ(51, 'Joe Lane', '650-555-0140'), 
                    person_typ(31, 'Sarah Chen', '415-555-0120'),
                    person_typ(52, 'Kim Patel', '650-555-0135')),
   physics_majors = 
        people_typ (person_typ(12, 'Bob Jones', '650-555-0130'), 
                    person_typ(45, 'Chris Woods', '415-555-0124'))
WHERE graduation = '01-JUN-03';

SELECT m.idno math_id, c.idno chem_id, p.idno physics_id  FROM students s,
 TABLE(s.math_majors) m, TABLE(s.chem_majors) c, TABLE(s.physics_majors) p;

ネストしたカーソルまたはTABLEファンクションを使用すると、ネストした表の個々の要素に簡単にアクセスできます。コレクションの問合せを参照してください。

5.1.7.3 ネストした表の格納時の表領域の指定

ネストした表は、親表と異なる表領域に格納できます。

例5-6では、ネストした表はsystem表領域に格納されます。

例5-6 ネストした表を格納するための別の表領域の指定

-- Requires Ex. 5-1, must remove code in Ex. 5-2 if created
CREATE TABLE people_tab (
    people_column people_typ )
    NESTED TABLE people_column STORE AS people_column_nt (TABLESPACE system);

TABLESPACE句が指定されていない場合、ネストした表の記憶表は、親表が作成された表領域に作成されます。マルチレベルのネストした表の場合、子表を、直系の親表と同じ表領域に作成します。

ALTER TABLE.. MOVE文を発行して、表を別の表領域に移動できます。ネストした表列を持つ表に対してこの文を発行した場合、親表のみ移動され、ネストした表の記憶表に対してはアクションは実行されません。ネストした表の記憶表を別の表領域に移動するには、記憶表に対してALTER TABLE.. MOVEを発行します。次に例を示します。

ALTER TABLE people_tab MOVE TABLESPACE system;  -- moving table
ALTER TABLE people_column_nt MOVE TABLESPACE example; -- moving storage table

people_tab表はsystem表領域に格納され、ネストした表記憶域はexample表領域に格納されました。

5.1.8 VARRAYおよびネストした表要素のサイズおよび精度の増加

VARRAY型の要素型またはネストした表型が可変文字、RAW型または数値型の場合、可変文字またはRAW型のサイズを大きくするか、数値型の精度を向上できます。

VARRAY型またはネストした表型の新しい型バージョンが生成されます。

これらの変更は、ALTER TYPE..MODIFY文を使用して行います。この文には次のオプションがあります。

CASCADE: 変更をその型および表の依存オブジェクトに伝播します。

関連項目:

CASCADEの詳細な説明は、「型進化に使用するALTER TYPE文」を参照してください

例5-7では、VARRAYおよびネストした表の要素の型のサイズを大きくします。

例5-7 VARRAYおよびネストした表の要素の型のサイズの増加

CREATE TYPE email_list_arr AS VARRAY(10) OF VARCHAR2(80);
/
ALTER TYPE email_list_arr MODIFY ELEMENT TYPE VARCHAR2(100) CASCADE;

CREATE TYPE email_list_tab AS TABLE OF VARCHAR2(30);
/
ALTER TYPE email_list_tab MODIFY ELEMENT TYPE VARCHAR2(40) CASCADE;

5.1.9 VARRAYの制限サイズの増加

ALTER TYPE ... MODIFY LIMIT構文を使用して、VARRAY型の要素の数を増加できます。

VARRAY型の要素の数を増すと、VARRAY型の新しい型バージョンが生成され、型変更履歴の一部となります。

ALTER TYPE ... MODIFY LIMIT文には次のオプションがあります。

  • INVALIDATE: すべての依存オブジェクトを無効とします。

  • CASCADE: 変更をその型および表の依存オブジェクトに伝播します。

例5-8 VARRAYの制限サイズの増加

-- if you have already creating following types, drop them.
DROP TYPE email_list_tab FORCE;
DROP TYPE email_list_arr FORCE;
CREATE TYPE email_list_arr AS VARRAY(10) OF VARCHAR2(80);
/
CREATE TYPE email_list_typ AS OBJECT (
    section_no   NUMBER, 
    emails       email_list_arr);
/

CREATE TYPE email_varray_typ AS VARRAY(5) OF email_list_typ;
/

ALTER TYPE email_varray_typ MODIFY LIMIT 100 INVALIDATE;

VARRAY型が変更されると、その変更は依存表に伝播されます。

5.1.10 LOB参照が含まれているVARRAYの作成

LOB参照のVARRAYを作成するには、まずREF型のVARRAY型を定義します。

注意: 次の例では、例5-8で定義したemail_list_typを参照しています。この例では、表dept_email_listを作成し、その中に配列型の列email_addrsを定義します。

例5-9 LOB参照を含むVARRAYの作成

-- Requires Ex. 5-8
CREATE TYPE ref_email_varray_typ AS VARRAY(5) OF REF email_list_typ;
/

CREATE TABLE dept_email_list (
  dept_no NUMBER, 
  email_addrs ref_email_varray_typ)
  VARRAY email_addrs STORE AS LOB dept_emails_lob3;