Oracle で配列型(ARRAY)を試してみました。
作り方は以下。まず create type で型を作ってから、create table でその型を列の型として指定します。
create type VARCHAR2_ARRAY as varray(5) of varchar2(10) create table TAB1 ( NO number(5), LIST VARCHAR2_ARRAY ) ;
insert は "型名(データの列挙)" って感じで書けるようです。
insert into TAB1 values (10, VARCHAR2_ARRAY('AA', 'BB', 'CC', 'DD', 'EE'));
insert into TAB1 values (11, VARCHAR2_ARRAY('A1', 'B1', 'C1', 'D1', 'E1'));
insert into TAB1 values (12, VARCHAR2_ARRAY('A2', 'B2', 'C2'));
insert into TAB1 values (13, VARCHAR2_ARRAY('Z3', 'B2', 'C2'));
 sql*plus 上で select してみるとこんな感じ。
 データは見えるけど命令文みたいでちょっと面白くない感じですね。
SQL> select * from TAB1;
        NO LIST
---------- --------------------------------------------------
        10 VARCHAR2_ARRAY('AA', 'BB', 'CC', 'DD', 'EE')
        11 VARCHAR2_ARRAY('A1', 'B1', 'C1', 'D1', 'E1')
        12 VARCHAR2_ARRAY('A2', 'B2', 'C2')
        13 VARCHAR2_ARRAY('Z3', 'B2', 'C2')
普通の列みたいに見えないか?と思って調べたところ、TABLE 演算子というのがあり、これを使うと配列を表の行データに分解してくれるようです。(コレクション・ネスト解除、というらしい)
SQL> select
  2     ROWNUM,
  3     COLUMN_VALUE
  4  from
  5     TABLE (
  6             select LIST
  7             from TAB1
  8             where NO=11
  9     )
 10  ;
    ROWNUM COLUMN_VALUE
---------- --------------------
         1 A1
         2 B1
         3 C1
         4 D1
         5 E1
ただこの TABLE 演算子、複数行の入力ができず、クエリの結果は必ず単一行/単一インスタンスでないとならないので、上記コードの 8 行目の where を外すとエラーになってしまいます。
なのでたとえば、全行の配列要素(=index)が 2 のものだけ抽出…というと、以下のコードを書く必要があります。
SQL> select * 2 from 3 ( 4 select 5 NO, 6 row_number() over(partition by NO order by N) as ARRAY_INDEX, -- [3] 7 ARRAY_VALUE 8 from 9 ( 10 select -- [2] 11 A.NO, 12 ROWNUM as N, 13 C.COLUMN_VALUE as ARRAY_VALUE 14 from -- [1] 15 TAB1 A, 16 TABLE( 17 select 18 LIST 19 from 20 TAB1 B 21 where 22 B.NO = A.NO 23 ) C 24 ) 25 ) 26 where 27 ARRAY_INDEX = 2 -- [4] 28 ; NO ARRAY_INDEX ARRAY_VALUE ---------- ----------- -------------------- 10 2 BB 11 2 B1 12 2 B2 13 2 B2
上記のコードがやっていることは以下のようなことです。
- コレクション・ネスト解除した配列の表と、元の表を結合します。
 - とりあえず、配列の格納順を保存するために rownum を含めて射影します。
# この rownum は順序を保存しているだけなので配列の要素番号とは異なります。
# 今回データの場合だと16件ヒットするので、1~16が振られています。 - NO で分割(Partition)します。
# partition ではソート列を指定する必要があるので、ここで先ほどの rownum 列を指定します。
# 求める値は分割後の行番号(row_number)にします。これが配列の要素番号になります。 - 配列の要素番号を指定し、絞り込みます。
 
OLAP 関数使ってまで…って感じでちょっといまいちです。# 誰かほかにいい方法を知っていたら教えてください(汗
 まあ配列型を SQL で扱おうとすること自体がダウト、なのかもしれません。
 PL/SQL で配列の要素を参照する場合は以下のような感じ。
SQL> set serveroutput on
SQL> declare
  2    ar VARCHAR2_ARRAY;
  3  begin
  4    select LIST into ar from TAB1 where NO=11;
  5    dbms_output.put_line(ar(2));
  6  end;
  7  /
B1
PL/SQLプロシージャが正常に完了しました。
 全行の配列要素(=index)が 2 のものだけを表示したい場合は以下。
 ずいぶんとすっきりします。
SQL> set serveroutput on
SQL> declare
  2  begin
  3      for row in (select LIST from TAB1) loop
  4          dbms_output.put_line(row.LIST(2));
  5      end loop;
  6  end;
  7  /
BB
B1
B2
B2
PL/SQLプロシージャが正常に完了しました。
			
[PostgreSQL] PostgreSQL で配列要素を SQL で選択する | オールトの雲
[…] [Oracle] VARRAY の要素を SQL で選択する […]
Link | 2014年4月15日 01:03