[Oracle] SQLでネストした表やVARRAYを表として扱う | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

TABLE演算子と CAST演算子を使うと、SQLで VARRAY、ネストした表といったコレクションを要素ごとの行にばらし、表のように扱うことができます。

ネストした表の例

CREATE TYPE object_type IS OBJECT (
  col1  VARCHAR2(100),
  col2  NUMBER(10)
)
/

CREATE TYPE object_table_type IS TABLE OF object_type
/

DECLARE

  object_table  object_table_type;

  CURSOR cur IS
    SELECT *
      FROM TABLE(CAST(object_table AS object_table_type));

  wk_rec  cur%ROWTYPE;

BEGIN
  object_table := object_table_type(
                    object_type('A',1),
                    object_type('B',2),
                    object_type('C',3),
                    object_type('D',4),
                    object_type('E',5)
                  );
  OPEN cur;
  LOOP
    FETCH cur INTO wk_rec;
    EXIT WHEN cur%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(wk_rec.col1 || ',' || wk_rec.col2);
  END LOOP;
  CLOSE cur;
END;
/

OBJECT型のネストした表を定義し、各OBJECT型要素を行として取り出し、OBJECT型要素内の各属性を列として取り出します。


VARRAYの例

CREATE TYPE number_array_type IS VARRAY(5) OF NUMBER
/

DECLARE

  number_array  number_array_type;

  CURSOR cur IS
    SELECT *
      FROM TABLE(CAST(number_array AS number_array_type));

  wk_num       NUMBER;

BEGIN
  number_array := number_array_type(1,2,3,4,5);
  OPEN cur;
  LOOP
    FETCH cur INTO wk_num;
    EXIT WHEN cur%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(wk_num);
  END LOOP;
  CLOSE cur;
END;
/

VARRAYの各要素を行として取り出します。
(VARRAYの場合、列名は何になるんでしょう...?)


このようにしてコレクションの要素を抽出するプロセスのことを「コレクション・ネスト解除」と呼ぶそうです。

データベースに永続表として格納するような性質ではないけれども、プログラム内で表として扱いたい...そんな場面で重宝する機能です。


ただし、これが可能なのは使用するコレクション型をスキーマ・レベルで定義している(CREATE TYPEで定義している)場合のみのようです。

コレクション型をローカル・レベルで定義している(PL/SQLブロック内で定義している)場合は、以下のエラーが発生します。
 

PLS-00642: SQL文ではローカル・コレクション型は使用できません。


便利な機能だと思うのですが、CREATE TYPE を使うことによって、プロシージャやパッケージ内で完結できなくなってしまうのがちょっと残念ですね。