連想配列の使用

連想配列は、コレクションの1つのタイプです。

関連情報:

コレクションの詳細は、次を参照してください。

コレクションについて

コレクションは、指定した順序と同じ型の要素を格納するPL/SQLのコンポジット変数で、一次元配列に似ています。コレクションの内部コンポーネントは、要素と呼ばれます。各要素には、コレクションでの位置を示す一意のサブスクリプトが含まれます。

コレクション要素にアクセスするには、collection_name(element_subscript)のような添字表記を使用します。

コレクション要素はスカラー変数のように処理できます。また、コレクション全体をサブプログラムのパラメータとして渡すこともできます(送信または受信サブプログラムのどちらもスタンドアロンのサブプログラムでない場合)。

コレクション・メソッドは、組込みPL/SQLサブプログラムで、 コレクションに関する情報を戻すか、 コレクションに対する操作を実行します。コレクション・メソッドを起動するには、ドット表記法: collection_name.method_nameを使用します。たとえば、collection_name.COUNTはコレクション内の要素の数を戻します。

PL/SQLには、次の3種類のコレクションがあります。

このドキュメントでは、連想配列についてのみ説明します。

関連情報:

連想配列について

連想配列は、キー/値のペアのバインドされていないセットです。各キーは固有で、該当する値を保持する要素のサブスクリプトとして使用されます。このため、配列内の場所を知らなくても、配列をトラバースせずに要素にアクセスできます。

キーのデータ型は、PLS_INTEGERまたはVARCHAR2 (長さ)です。

キーのデータ型がPLS_INTEGERで、連想配列が整数で索引付けされ稠密(つまり、要素間に差異がない)である場合、最初と最後の要素の間のすべての要素が定義されており、それぞれに値があります(値はNULLの場合もあります)。

キー・タイプがVARCHAR2 (長さ)の場合、連想配列は文字列(2文字)で索引付けされてスパースです。つまり、要素間に差異がある可能性があります。

稠密な連想配列をトラバースする場合、要素間の差異を考慮する必要はありません。スパースな連想配列をトラバースする場合は、要素間の差異を考慮する必要があります。

連想配列の要素に値を割り当てるには、代入演算子を使用できます。

array_name(key) := value

キーが配列にない場合、代入文によって配列にキーと値のペアが追加されます。それ以外の場合、この文はarray_name(key)の値を値に変更します。

連想配列は、データを一時的に格納する場合に有用です。表が必要とするディスク領域またはネットワーク操作を使用しません。ただし、連想配列は、データを一時的に格納する用途のため、DML文で操作できません。

パッケージ内で連想配列を宣言し、パッケージ本体の変数に値を割り当てると、連想配列はデータベース・セッションの存続期間中に存在します。そうでない場合は、宣言したサブプログラムの存続期間中に存在します。

関連項目:連想配列の詳細は『Oracle Database PL/SQL言語リファレンス』を参照してください。

連想配列の宣言

連想配列を宣言するには、連想配列の型を宣言し、その型の変数を宣言します。

次のコードは、最も単純な構文を示しています。

TYPE array_type IS TABLE OF element_type INDEX BY key_type;

array_name  array_type;

連想配列を宣言する効果的な方法は、次の手順を実行して、カーソルを使用することです。この手順では、最も単純な形式で必要な各文を使用し、複雑な構文への参照も提示します。

カーソルを使用して連想配列を宣言するには:

  1. 宣言部で次を実行します。

    1. カーソルを宣言します。

       CURSOR cursor_name IS query;
      

      宣言カーソルの宣言構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

    2. 連想配列の型を宣言します。

       TYPE array_type IS TABLE OF cursor_name%ROWTYPE
         INDEX BY { PLS_INTEGER | VARCHAR2 length }
      

      連想配列の型の構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

    3. その型の連想配列の変数を宣言します。

       array_name  array_type;
      

      変数値の宣言構文の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

例5-9では、前述の手順を使用して2つの連想配列employees_jobsおよびjobs_を宣言し、カーソルを使用せずに3つ目の連想配列job_titlesを宣言します。1つ目と2つ目の配列は整数で索引付けされ、3つ目は文字列によって索引付けされます。

ノート: employees_jobs_cursorの宣言内のORDER BY句によって、連想配列employee_jobsの要素の格納順が決定されます。

例5-9 連想配列の宣言

DECLARE
  -- Declare cursor:

  CURSOR employees_jobs_cursor IS
    SELECT FIRST_NAME, LAST_NAME, JOB_ID
    FROM EMPLOYEES
    ORDER BY JOB_ID, LAST_NAME, FIRST_NAME;

  -- Declare associative array type:

  TYPE employees_jobs_type IS TABLE OF employees_jobs_cursor%ROWTYPE
    INDEX BY PLS_INTEGER;

  -- Declare associative array:

  employees_jobs  employees_jobs_type;

  -- Use same procedure to declare another associative array:

  CURSOR jobs_cursor IS
    SELECT JOB_ID, JOB_TITLE
    FROM JOBS;

  TYPE jobs_type IS TABLE OF jobs_cursor%ROWTYPE
    INDEX BY PLS_INTEGER;

  jobs_  jobs_type;

-- Declare associative array without using cursor:

  TYPE job_titles_type IS TABLE OF JOBS.JOB_TITLE%TYPE
    INDEX BY JOBS.JOB_ID%TYPE;  -- jobs.job_id%type is varchar2(10)

  job_titles  job_titles_type;

BEGIN
  NULL;
END;
/

関連情報:

連想配列の移入

通常、稠密な連想配列を移入する最も効率的な方法は、SELECT文にBULK COLLECT INTO句を使用することです。

ノート:稠密な連想配列が非常に大きいため、SELECT文が大きすぎてメモリーに収まらない結果セットを戻す場合、SELECT文を使用しないでください。かわりに、カーソルおよびFETCH文にBULK COLLECT INTO句およびLIMIT句を移入してください。BULK COLLECT INTO句を含むFETCH文の使用の詳細は、Oracle Database PL/SQL言語リファレンスに関する項を参照してください。

SELECT文を使用して、スパースな連想配列(「連想配列を宣言」のjob_titlesなど)を移入できません。そのかわり、ループ文内部に代入文を使用する必要があります。ループ文の詳細は、プログラム・フローの制御を参照してください。例5-10では、SELECT文を使用して、整数によって索引付けされるemployees_jobsおよびjobs_を連想配列に移入します。次に、FOR LOOP文内部の代入文を使用して、文字列で索引付けされる連想配列job_titlesを移入します。

例5-10 連想配列の移入

-- Declarative part from Example 5-9 goes here.

BEGIN
  -- Populate associative arrays indexed by integer:

SELECT FIRST_NAME, LAST_NAME, JOB_ID BULK COLLECT INTO employees_jobs
  FROM EMPLOYEES ORDER BY JOB_ID, LAST_NAME, FIRST_NAME;

SELECT JOB_ID, JOB_TITLE BULK COLLECT INTO jobs_ FROM JOBS;

  -- Populate associative array indexed by string:

  FOR i IN 1..jobs_.COUNT() LOOP
    job_titles(jobs_(i).job_id) := jobs_(i).job_title;
  END LOOP;
END;
/

関連項目: カーソルについて

稠密な連想配列のトラバース

稠密な連想配列(整数による索引付け)には、要素間の差異がなく、最初と最後の要素の間のすべての要素が定義されていて、それぞれに値があります(値はNULLの場合もあります)。

例5-11のように、FOR LOOP文で稠密な配列を横断できます。

例5-10の実行可能部分に挿入すると、例5-11の実行可能部分に挿入すると、employees_jobs配列を移入するコードの後に、employees_jobs配列の要素を、格納された順序で出力します。格納順序は、employees_jobsを宣言するために使用されたemployees_jobs_cursor宣言のORDER BY句によって決定されました(例5-9を参照)。

FOR LOOP文の上限employees_jobs.COUNTは、配列内の要素の数を戻すコレクション・メソッドを起動します。COUNTの詳細は、『Oracle Database PL/SQL言語リファレンス』に関する項を参照してください。

例5-11 稠密連想配列の横断

-- Code that populates employees_jobs must precede this code:

FOR i IN 1..employees_jobs.COUNT LOOP
  DBMS_OUTPUT.PUT_LINE(
    RPAD(employees_jobs(i).first_name, 23) ||
    RPAD(employees_jobs(i).last_name,  28) ||     employees_jobs(i).job_id);
  END LOOP;

結果:

William                Gietz                       AC_ACCOUNT
Shelley                Higgins                     AC_MGR
Jennifer               Whalen                      AD_ASST
Steven                 King                        AD_PRES
Lex                    De Haan                     AD_VP
Neena                  Kochhar                     AD_VP
John                   Chen                        FI_ACCOUNT
...
Jose Manuel            Urman                       FI_ACCOUNT
Nancy                  Greenberg                   FI_MGR
Susan                  Mavris                      HR_REP
David                  Austin                      IT_PROG
...
Valli                  Pataballa                   IT_PROG
Michael                Hartstein                   MK_MAN
Pat                    Fay                         MK_REP
Hermann                Baer                        PR_REP
Shelli                 Baida                       PU_CLERK
...
Sigal                  Tobias                      PU_CLERK
Den                    Raphaely                    PU_MAN
Gerald                 Cambrault                   SA_MAN
...
Eleni                  Zlotkey                     SA_MAN
Ellen                  Abel                        SA_REP
...
Clara                  Vishney                     SA_REP
Sarah                  Bell                        SH_CLERK
...
Peter                  Vargas                      ST_CLERK
Adam                   Fripp                       ST_MAN
...
Matthew                Weiss                       ST_MAN

スパースな連想配列のトラバース

スパースな連想配列(文字列による索引付け)は、要素間に差異がある可能性があります。

例5-12のように、WHILE LOOP文で横断できます。

例5-12でコードを実行し、job_titles配列の要素を出力するには、次のステップを実行します。

  1. 例5-9の宣言部分の終わりに、次の変数宣言を挿入してください。

     i jobs.job_id%TYPE;
    
  2. 例5-10の実行可能部分で、job_titles配列を移入するコードの後に、例5-12のコードを挿入します。

例5-12 スパース連想配列の横断

/* Declare this variable in declarative part:

   i jobs.job_id%TYPE;

   Add this code to the executable part,
   after code that populates job_titles:
*/

i := job_titles.FIRST;

WHILE i IS NOT NULL LOOP
  DBMS_OUTPUT.PUT_LINE(RPAD(i, 12) || job_titles(i));
  i := job_titles.NEXT(i);
END LOOP;

結果:

AC_ACCOUNT  Public Accountant
AC_MGR      Accounting Manager
AD_ASST     Administration Assistant
AD_PRES     President
AD_VP       Administration Vice President
FI_ACCOUNT  Accountant
FI_MGR      Finance Manager
HR_REP      Human Resources Representative
IT_PROG     Programmer
MK_MAN      Marketing Manager
MK_REP      Marketing Representative
PR_REP      Public Relations Representative
PU_CLERK    Purchasing Clerk
PU_MAN      Purchasing Manager
SA_MAN      Sales Manager
SA_REP      Sales Representative
SH_CLERK    Shipping Clerk
ST_CLERK    Stock Clerk
ST_MAN      Stock Manager

Example 5-12 includes two collection method invocations, job_titles.FIRST and job_titles.NEXT(i). job_titles.FIRST returns the first element of job_titles, and job_titles.NEXT(i) returns the subscript that succeeds i. FIRSTの詳細は、『Oracle Database PL/SQL言語リファレンス』に関する項を参照してください。NEXTの詳細は、『Oracle Database PL/SQL言語リファレンス』に関する項を参照してください。