HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

SQLクエリメモ - XMLデータをリレーショナルデータに変換するクエリ

ふとしたこと(何)から、次のような構造を持つXMLデータが格納されたテーブルから、リレーショナルな構造を持つ別のテーブルへkey-valueの組をコピーするクエリを書いた。

<path>
    <to key="k1" val="v1"/>
    <to key="k2" val="v2"/>
</path>

いわゆる繰り返し構造になっているのが今回のポイント。
テーブルの構造は次のような感じ。

TBL1:
    |id (VARCHAR(8))|data (XML)|
TBL2:
    |id (VARCHAR(8))|key (VARCHAR(8))|val (VARCHAR(8))|

せっかく書いたので(謎)、クエリメモとして晒しておく。

CREATE TABLE tbl1(
      id VARCHAR(8)
    , data XML)
;
CREATE TABLE tbl2(
      id VARCHAR(8)
    , key VARCHAR(8)
    , val VARCHAR(8))
;

INSERT INTO tbl1(id, data)
    VALUES(
          '00000001'
        , '<path><to key="k1" val="v1"/><to key="k2" val="v2"/></path>'
    );
INSERT INTO tbl1(id, data)
    VALUES(
          '00000002'
        , '<path><to key="k1" val="v1"/><to key="k2" val="v2"/><to key="k3" val="v3"/></path>'
    );

INSERT INTO tbl2(id, key, val)
    SELECT t.id, x.key, x.val
    FROM tbl1 AS t, XMLTABLE('$root/path/to' PASSING t.data AS "root"
        COLUMNS key varchar(8) PATH './@key'
              , val varchar(8) PATH './@val') AS x;

SELECT id, key, val FROM tbl2;

DROP TABLE tbl2;
DROP TABLE tbl1;

ちなみに、最後のほうのSELECT文の実行結果は次のようになる。

ID       KEY      VAL
-------- -------- --------
00000001 k1       v1
00000001 k2       v2
00000002 k1       v1
00000002 k2       v2
00000002 k3       v3