XMLTABLE の例証: 第 2 回 DB2 での一般的な XMLTABLE の使用例

この SQL/XML 関数を最大限利用する

XMLTABLE は SQL/XML 標準のなかでもとりわけ強力な関数で、IBM® DB2® 9 for Linux®, Unix®, and Windows® だけでなく DB2 9 for z/OS® でも使用することができます。XMLTABLE についての 2 回連載の第 1 回では、XMLTABLE を使用してリレーショナル・フォーマットで XML データを取得する方法、繰り返しの XML 要素や欠落した XML 要素に対処する方法、そして XMLTABLE 関数で名前空間を処理する方法を説明しました。第 2 回となる今回の記事では、一般的な XMLTABLE の使用例を取り上げます。具体的には、XML のリレーショナル・テーブルへのシュレッディング、大規模な文書の分割、XML 文書の XML データとリレーショナル・データのハイブリッド・ストレージの生成、そして XML データのリレーショナル・ビューの使用です。この記事で紹介する手法とサンプルを参考に、DB2 9 pureXML で強力な XML アプリケーションを開発してください。

Vitor Rodrigues (vrodrig@us.ibm.com), DB2 pureXML Technical Enablement, IBM

photo2Vitor Rodrigues は IBM Silicon Valley Lab のソフトウェア開発者です。コンピューター・サイエンスとシステム・エンジニアリングの専攻でポルトガルの University of Minho を卒業しています。2005年、DB2 Everyplace と DB2 9 pureXML 担当のインターンとして IBM に参加し、pureXML の DB2 9 QA チームの一員として DB2 9 の XML 機能に関する深い知識を身につけました。彼はインターンシップの後、正規社員となり、現在は DB2 9 XML Enablement チームに所属しています。



Matthias Nicola (mnicola@us.ibm.com), DB2/XML Performance, IBM Silicon Valley Laboratory

Author photo: Matthias NicolaNicola 博士は、IBM Silicon Valley Lab の XML データベース・パフォーマンスの技術リーダーです。彼の業務は、XQuery、SQL/XML、また DB2 ネイティブの XML 機能を含め、DB2 での XML パフォーマンスのあらゆる側面を対象としています。Nicola 博士は DB2 XML 開発チームや XML を使用する顧客やビジネス・パートナーと緊密に業務を進めながら、XML ソリューションの設計や実装、最適化に協力しています。IBM に入社する前には、Informix Software でデータ・ウェアハウスのパフォーマンスに関する業務を行っていました。また、分散データベースや複製データベースに関する研究と業界プロジェクトにも 4 年間携わっていました。彼は、1999年にドイツの Technical University of Aachen でコンピューター・サイエンスの博士号を取得しています。



2007年 9月 13日

サンプル・データ

この記事の XMLTABLE シナリオの説明では、連載第 1 回で使用したサンプル・テーブルとデータを引き続き使用します。このテーブルを構成するのは 1 つの XML 列と 2 つの行です。それぞれの行には 1 つの XML 文書がリストされています。最初の文書は従業員が 2 人いる部門、2 番目の文書は従業員が 1 人だけの部門を記述しています。

表 1. サンプル・テーブルおよびデータ
create table emp (doc XML);
<dept bldg="101">
	<employee id="901">
		<name>
			<first>John</first>
			<last>Doe</last>
		</name>
		<office>344</office>
		<salary currency="USD">55000</salary>
	</employee>
	<employee id="902">
		<name>
			<first>Peter</first>
			<last>Pan</last>
		</name>
		<office>216</office>
		<phone>905-416-5004</phone>
	</employee>
</dept>
<dept bldg="114">
	<employee id="903">
		<name>
			<first>Mary</first>
			<last>Jones</last>
		</name>
		<office>415</office>
		<phone>905-403-6112</phone>
		<phone>647-504-4546</phone>
		<salary currency="USD">64000</salary>
	</employee>
</dept>

XMLTABLE には、XML データをリレーショナル・フォーマットで返すという基本的な使用法の他にも、さまざまな用途があります。


大規模な XML 文書から小さな複数の文書への分割

たいていのプログラマーは、アプリケーションの論理ビジネス・オブジェクトとアクセスの主な粒度に合わせた単位で XML 文書を扱うのが便利で効率的だと考えています。そのため通常、得策とされるのは、例えば発注書ごと、取引ごと、契約ごと、納税申告ごと、顧客ごとに XML 文書を分けることです。XML 設計とオーサリング・ツールを使う場合はなおさらのこと、小さな文書のほうが大きな文書よりも効率的に操作できます。さらに文書が小さければ、索引によるアクセスとデータ検索の時間も短縮されることになります。

しかしその一方、FTP などでデータベース外部に XML データをバルク転送する場合には、数千あるいは数百万の文書を処理するとなると不都合です。そのため、一般的に受信するのは大きな XML 文書で、それぞれのファイル・サイズは数百メガバイトになることもあり、文書内では独立したオブジェクトを表すブロックが何度も繰り返されています。このような大規模な XML 文書を開こうとして外部ツールが失敗したり、あるいは重大な問題が発生することは珍しくありません。通常その原因は、文書オブジェクト・モデル (DOM) の解析およびメモリーの制約によるものです。

DB2 では XML 文書を最大 2GB まで取り込めますが、XMLTABLE 関数を使って XML 文書を小さな文書に分割するというオプションもあります。その一例として、表 1のデータを使用してみましょう。文書ごとに従業員をリストするこの表では、従業員データが部門別に集約されています。クエリー 1 を INSERT 文に組み込むと、部門文書から各従業員が抽出され、employee テーブルの個別の行にそれぞれ独立した XML 文書として挿入されます。

クエリー 1. XMLTABLE による文書の分割
create table employee(doc XML)

INSERT INTO employee
SELECT X.* FROM 
  XMLTABLE ('$d/dept/employee' passing cast(? As XML) as "d" 
    COLUMNS 
      doc XML PATH 'document{.}') AS X

このクエリーの XMLTABLE 関数は、従業員ごとに XML 型を 1 列持つ 1 行のデータを作成します。passing 節の「?」が示すのは、XML 文書をステートメントへの入力として提供するパラメーター・マーカーです。このパラメーター・マーカーは、cast (? as XML) によって XML 型にキャストされます。パラメーター・マーカーを使う代わりにリテラル XML 文書をステートメントへの入力として使用することもできますが、そうすると通常は体裁が悪くなるため、極めて小さい文書でない限り実用的ではありません。したがって、パラメーター・マーカーが推奨されます。

XML データ・モデルには、(文書の単一ルート要素の親として) 1 つの文書ノードを持つ構文解析済みの整形式 XML 文書が必要です。この文書ノードは XML 文書のテキストの (シリアライズされた) 表現には現れません。入力文書から抽出された従業員サブツリーには文書ノードがないので、そのままでは整形式文書として挿入することができません。そのため、document{} コンストラクターが抽出された従業員ごとに文書ノードを作成しています。


XML 文書からリレーショナル・データへの分解

INSERT 文で XMLTABLE クエリーを使用するという方法は、XML データをリレーショナル・テーブルにシュレッド (分解) する場合にも役立ちます。例えば、XML がメッセージ・フォーマットとしてのみ使用されている場合がありますが、この場合メッセージをいったん受信してしまえば後は XML を保持する必要はありません。したがって、メッセージの XML ペイロードを SQL アプリケーションにフィードするために既存のリレーショナル・テーブルに簡単にマッピングできるとしたら、XML データをリレーショナル・データにシュレッドするのがもっともなやり方です。一方、複雑で変わりやすい XML スキーマを伴うシナリオの場合は、リレーショナル・データへのシュレッドはかなり困難になるので、pureXML ストレージのほうが賢いオプションとなります。

前と同じサンプルに従ったクエリー 2 では、今度は従業員データを新しいリレーショナル・テーブル、employeeRel にシュレッドするために XMLTABLE を使用しています。このテーブルでは従業員ごとに 1 行のデータが生成されます。

クエリー 2. XMLTABLE による XML データのリレーショナル・フォーマットへの分解
create table employeeRel(bldg integer, id integer, fname varchar(15),
                         lname varchar(15), office integer)

INSERT INTO employeeRel
  SELECT X.* FROM 
     XMLTABLE ('$d/dept/employee' passing cast (? as XML) as "d" 
       COLUMNS 
         building	INTEGER	PATH '../@bldg'
         empID	INTEGER	PATH '@id',
         firstname	VARCHAR(15)	PATH 'name/first',
         lastname	VARCHAR(15)	PATH 'name/last',
         office	INTEGER	PATH 'office') AS X

このシナリオでは、文書に含まれる要素のサブセットのみをシュレッドしています。phone 要素と salary 要素はシュレッドしていませんが、追加するのは簡単です。ここではとりあえず、上記の employeeRel テーブルに対する SELECT 文が返す出力を以下に示します。

BLDG   ID    FNAME                LNAME               OFFICE
----- ------ -------------------- ------------------- -----
101    901   John                 Doe                 344
101    902   Peter                Pan                 216
114    903   Mary                 Jones               415

  3 record(s) selected.

既存の XML 列にある XML 文書をシュレッドすることも可能です。この場合、この後記載するクエリー 5 や連載第 1 回に記載したクエリーのほとんどがそうであったように、クエリー 2 の行生成式にはパラメーター・マーカーではなく、単に列名を渡すことになります。


ハイブリッド手法: XML とリレーショナル

リレーショナル・フォーマットと XML フォーマットのデータを混在させるのが理に適っているという場合もあります。構造化された固定データ項目は時間が経っても変更されることはまずないので、このようなデータにはリレーショナル列を選択するのが適切です。その一方、データの他の部分が半構造化、可変、または本質的な階層データである場合は、XML 列に保管するほうが適しています。このハイブリッド手法を挿入時に実現する方法として一般的なのは、選択した要素または属性を各 XML 文書から抽出し、完全な文書を挿入する行と同じ行のリレーショナル列に配置することです。その上で、リレーショナル列に複数列索引 (複合キー)、参照整合性の制約、あるいはトリガーを必要に応じて定義します。これらの概念は XML 列に対しては使用できないか、あるいは部分的にしか有効でないためです。

テーブルのリレーショナル列と XML 列に併せてデータを設定する方法はさまざまにあります。アプリケーションで値の抽出を行い、XML 文書と抽出した値の両方を SQL の INSERT 文にフィードすることもできますが、たいていの場合は単に INSERT 文内で XMLTABLE を使うだけのほうがわかりやすく簡単です。このようにすれば、アプリケーションで XML を構文解析することなく、INSERT 文にロジックを保持することができます。のちに変更が必要になった場合は、アプリケーション・コードを修正する代わりに、(おそらくストアード・プロシージャーにカプセル化された) このINSERT 文を変更すればよいだけとなります。

クエリー 3 に、bldg 属性をINTEGER 型の別の列に抽出した上で表 1の部門文書を挿入する方法を示します。行生成式 $d にはナビゲーション、つまり XPath のステップが含まれていないことに注目してください。これは、COLUMNS 節のコンテキストは常に文書ノードが含まれる完全文書であることを意味します。

クエリー 3. 1 つの属性をリレーショナル列に抽出した上での XML データの挿入
create table hybridDept(bldg integer, doc XML);

INSERT INTO emp1
SELECT X.* FROM
XMLTABLE ('$d' passing cast(? as XML) as "d" 
        COLUMNS 
          building        INTEGER         PATH ' @bldg',
          doc             XML             PATH '.'
) AS X

クエリー 4 ではクエリー 3 と同じ XML 文書を挿入していますが、リレーショナル列に抽出しているのは従業員の ID、苗字と名前、そしてオフィス番号です。このクエリーは部門文書を分割して従業員ごとに XML 文書を 1 つ含む 1 行のデータを生成します。新しい文書は入力文書のフラグメントであるため、文書ノードの作成が必要となります。

クエリー 4. 複数の要素をリレーショナル列に保管した上での XML データの挿入
create table hybridEmp(id integer, fname varchar(25), 
                       lname varchar(25), doc XML);

INSERT INTO emp1
SELECT X.* FROM
XMLTABLE ('$d/dept/employee' passing cast(? as XML) as "d" 
	COLUMNS 
	id 	INTEGER		PATH ' @id',
	first 	VARCHAR(25) 	PATH 'name/first',
	last 	VARCHAR(25) 	PATH 'name/last',
	doc 	XML		PATH 'document{.}'
) AS X

XML データのリレーショナル・ビューの作成

これまでのセクションでは、XMLTABLE を使用して XML データをリレーショナル・テーブルにシュレッドする方法、そして XML データのハイブリッド表現を生成する方法を見てきましたが、同じ XMLTABLE 式をビュー定義に組み込むことも可能です。このようにすると、該当するフォーマットで実際にデータを保管しなくても、アプリ一ケーションに XML データのリレーショナル・ビューまたはハイブリッド・ビューを提供することができます。

ビュー定義に組み込まれたクエリー 5 は、doc 列の XML 要素および属性のサブセットをリレーショナル・フォーマットで公開します。アプリケーションでこのビューを利用すれば、ベースとなる実際のデータが XML フォーマットであっても、従来の SQL 文を使ってこのデータに対してクエリーを実行することができます。

クエリー 5. ビューを使用したリレーショナル・フォーマットでの XML データの公開
CREATE VIEW emp_rel (id, first_name ,last_name ,office) 
AS
SELECT X.* FROM emp,
  XMLTABLE ('$d/dept/employee' passing doc as "d" 
   COLUMNS 
      empID 		INTEGER 	PATH '@id',
      firstname		VARCHAR(5) 	PATH 'name/first',
      lastname		VARCHAR(5) 	PATH 'name/last',
      office		INTEGER 	PATH 'office') AS X

リレーショナル・ビューを使い慣れていれば、ビューの名前と列を定義するステートメントの先頭行は簡単に理解できるはずです。AS 節のクエリー式は、ビューのコンテンツを定義します。このサンプルでは XMLTABLE を使用して、XML データに含まれる従業員ごとに 1 行のデータを生成しています。各行を構成するのは 4 つのリレーショナル列で、それぞれに従業員 ID、苗字、名前、オフィス番号がリストされます。

クエリー 6 に示すのは、このビューに対して単純な SQL 文 (XML 拡張なし) を実行してオフィス 344 に所属する従業員の名前と ID を取得する方法です。

クエリー 6. SQL を使用した XMLTABLE ビューのクエリー
select id, first_name from emp_rel where office = 344;

ID          FIRST_NAME
----------- ----------
        901 John

  1 record(s) selected.

注意しなければならない点として、このような SQL 述部を使った SQL クエリーを XMLTABLE ビューに対して実行すると、DB2 はビューのすべてのリレーショナル行を生成してから SQL 述部を評価します。これはつまり、SQL クエリーが必要とするのは特定の 1 つの文書のデータだけだとしても、ベースとなるテーブルに含まれるすべての文書に XMLTABLE 関数が適用されるということです。そのため、パフォーマンスに悪影響を及ぼす場合があります。

具体的に言うと、SQL 述部はベースとなる基本テーブルではなくビューのリレーショナル列で表現されるため、DB2 は XML 索引を使用しないで SQL 述部を評価します。通常、データベース・システムでは簡単にリレーショナル述部を XML 述部に変換することはできません。次のセクションでは、この制約を回避するとともに十分なパフォーマンスを達成する方法について説明します。


XMLTABLE ビューに関するパフォーマンスの考慮事項

XMLTABLE ビューのクエリーで優れたランタイム・パフォーマンスを実現する鍵は、索引を適切に使用して、XMLTABLE 関数に入力される XML 文書の数を減らすことです。それには 2 つの方法があります。

  • XML 索引を指定した XML 述部を使用する
  • 索引付きリレーショナル列でリレーショナル述部を使用する

クエリー 6 の述部は、結局はベースとなる XML データの要素である office に関するものなので、ベースとなる XML 列の /dept/employee/office で索引を作成してクエリーを高速にすることもできます。クエリーがこの索引を使用するのは、述部が XML 述部として表現されている場合のみです。そのため、XML 列はビュー定義に組み込まれていなければなりません (クエリー 7 を参照)。

クエリー 7. XMLTABLE ビューへの XML 列の組み込み
CREATE VIEW emp_rel (id, first_name ,last_name ,office, doc) 
AS
SELECT X.* FROM emp,
  XMLTABLE ('$d/dept/employee' passing doc as "d" 
   COLUMNS 
      empID	INTEGER		PATH '@id',
      firstname	VARCHAR(5)	PATH 'name/first',
      lastname	VARCHAR(5)	PATH 'name/last',
      office	INTEGER	PATH 'office'
      doc      	XML	PATH 'document{.}'
) AS X

上記のようにした上でクエリー 6 を XML 述部を使って表現すれば、XML 索引が使用されてパフォーマンスが大幅に改善されます。その方法を示しているのがクエリー 8 です。このクエリーでは XML 述部が使用されていますが、SELECT リストは依然としてリレーショナル・ビュー列だけを参照するので、クエリー結果はリレーショナル・フォーマットで返されます。

クエリー 8. XML 述部を使った XMLTABLE ビューのクエリー
select id, first_name from emp_rel 
where xmlexists('$d/employee/[office = 344]' passing doc as "d")

ID          FIRST_NAME
----------- ----------
        901 John

  1 record(s) selected.

実際かなり一般的なことですが、ベースとなる基本テーブルに XML 列だけでなくリレーショナル列も含まれる場合は、XMLTABLE ビューに対するクエリーをさらに高速化することができます。この場合、これらのリレーショナル列もビュー定義に組み込んでください。クエリー 9 では、deptID および unit 列がビューに組み込まれています。

クエリー 9. XMLTABLE ビューへのリレーショナル列の組み込み
CREATE TABLE emp(deptId integer, unit char(20), doc XML)

CREATE VIEW emp_rel (deptId, unit, empid, first_name ,last_name ,office) 
AS
SELECT E.deptId, E.unit, X.* 
FROM emp E,
  XMLTABLE ('$d/dept/employee' passing doc as "d" 
   COLUMNS 
      empID		INTEGER	PATH '@id',
      firstname	VARCHAR(5)	PATH 'name/first',
      lastname	VARCHAR(5)	PATH 'name/last',
      office	INTEGER	PATH 'office'
) AS X

おそらく従業員情報のクエリーに含まれることになるのは、deptID または unit、あるいはその両方に関する述部です。これらの述部が十分に選択を絞れるものであれば、XMLTABLE 処理のコストは劇的に削減されます。クエリー 10 では、deptID に関する述部が追加されています。DB2 はこの述部を最初に評価するので、XMLTABLE 関数は部門 9473 の従業員にしか適用されません。テーブル全体のサイズに比べれば、このセットは取るに足らない大きさです。2 番目の述部が、該当する従業員のなかからオフィス 344 の従業員を素早く検出します。

クエリー 10. リレーショナル述部を使った XMLTABLE ビューのクエリー
select id, first_name from emp_rel 
where deptID = 9473 and office = 344

ID          FIRST_NAME
----------- ----------
        901 John

  1 record(s) selected.

文書に対して生成される行の番号付け

時には、XMLTABLE が特定の文書に対して生成する行に番号を付ける列を生成したいという場合もあります。このようにすれば、各文書での値の表示順をアプリケーションに記憶させることができます。このような列を生成するために使用するのは、DB2 9.5 でサポートされている「for ordinality」節です。クエリー 11 でこの機能を実演してみます。XMLTABLE 関数に入力される各文書に対して、番号は 1 から付けられていることに注意してください。

クエリー 11. 「for ordinality」によってシーケンス番号を生成する XMLTABLE クエリー
SELECT X.* 
FROM emp, 
XMLTABLE ('$d/dept/employee' passing doc as "d" 
   COLUMNS 
   seqno       for ordinality,
   empID 	INTEGER 	PATH '@id',
   firstname 	VARCHAR(20) 	PATH 'name/first',
   lastname 	VARCHAR(25) 	PATH 'name/last') AS X

上記のクエリーを DB2 で実行すると、以下の結果が返ってきます。

seqno   empID       firstname            lastname
------- ----------- -------------------- -------------------------
      1         901 John                 Doe
      2         902 Peter                Pan
      1         903 Mary                 Jones

フィールドと値のペアのリスト

実際の XML アプリケーションでは、文書の構造や属性および要素名とは無関係に、特定の XML 文書に存在するフィールドと値のペアをすべてリストしなければならない場合もあります。このような場合にも、XMLTABLE 関数が役立ちます。

2 つの列 (tagname、value) が含まれるリレーショナル・テーブルを生成するには、XML 文書のすべての要素と属性をトラバースして、それぞれの要素および属性ごとに名前と値を抽出します。クエリー 12 は、XML データからすべての属性と値および要素と値のペアを返す一般的な方法です。この汎用クエリーは、さらに具体的なニーズに合わせて変更することができます。

クエリー 12 の行生成式 $d//(*, @*) に注目してください。ダブルスラッシュ (//) は XML 文書のすべてのレベルまで再帰的にトラバースします。$d//* または $d//@* のような式にすると、すべての要素、あるいはすべての属性が返ってきますが、両方を合わせたシーケンスにはなりません。$d//(*, @*) という式にすることで、すべての要素と属性が返されるようにしています。

クエリー 12. すべての属性と要素およびそれぞれの値のリスト作成
SELECT X.* FROM emp,
  XMLTABLE ('$d//(*, @*)' passing doc as "d" 
	COLUMNS 
	tagname VARCHAR(20)  PATH  'name()',
	value   VARCHAR(60)  PATH  'data(.)'
) AS X

クエリー 12 は XML データに含まれるノードごとに、そのノードの名前と値をリストしたリレーショナル行を返します。XML データ・モデルの定義により、リーフ・ノード以外のノードの値はすべての下位テキスト・ノードが連結された値となります。この定義は、クエリー 12 の結果に現れます。

TAGNAME              VALUE
-------------------- -----------------------------------------------
dept                 JohnDoe34455000PeterPan216905-416-5004
bldg                 101
employee             JohnDoe34455000
id                   901
name                 JohnDoe
first                John
last                 Doe
office               344
salary               55000
currency             USD
employee             PeterPan216905-416-5004
id                   902
name                 PeterPan
first                Peter
last                 Pan
office               216
phone                905-416-5004
dept                 MaryJones415905-403-6112647-504-454664000
bldg                 114
employee             MaryJones415905-403-6112647-504-454664000
id                   903
name                 MaryJones
first                Mary
last                 Jones
office               415
phone                905-403-6112
phone                647-504-4546
salary               64000
currency             USD

  29 record(s) selected.

連結された値はあまり実用的ではなく、他のエントリーと重複してしまいます。以下のように COLUMNS 節にもっと複雑な処理を行う式を作成すれば、より整然とした結果セットを生成することができます。

クエリー 13. 文書に含まれるあらゆる XML ノードに対する名前、型、値のリストの作成
SELECT X.* FROM emp ,
XMLTABLE ('$d//(*, @*)' passing doc as "d" 
  COLUMNS 
    tagname  VARCHAR(16) PATH  'name()',
    type     VARCHAR(12) PATH 'let $i := (if  (self::element()) 
				then (if (./*) then (''ELEMENT'') else (''LEAF-ELEMENT'')) 
               else (''ATTRIBUTE'')) return $i',
    value    VARCHAR(16) PATH '( .[self::element()]/text(),
                                 .[self::attribute()]/data(.) )'
  ) AS X

クエリー 12 と比べてクエリー 13 が異なる点は、value列に対する列生成式、そして typeという列が新たに追加されていることです。行生成式を任意の XQuery 式にできるのとまったく同じように、列生成式の場合も、割り当てられた SQL データ型にキャスト可能なスカラー値をそれぞれの式が返す限り XQuery 式にすることができます。

value 列では、要素の下位テキスト・ノードを連結せずに、各要素の直接のテキスト・ノードの子だけを返すようにしています。これを実現するために使用しているのが、text() 関数です。属性ノードに対しては、text() 関数ではなく data() 関数を使っていますが、その理由は、属性の値は個別のテキスト・ノード内には存在しないからです。data() 関数も同じく要素の下位テキスト・ノードを返すため、この記事では要素ノードに対してはこの関数を使用しません。代わりにニーズを満たすために使用しているのは、述部 (.[self::element()]/text(),.[self::attribute()]/data(.)) です。現行ノードが要素であれば、その要素のテキスト・ノードが text() 関数によって返され、現行ノードが属性であれば data() 関数によってその属性の値が返されるようにしています。

もう 1 つ、クエリー 13クエリー 12 と大きく異なる点は、新しい type 列が追加されていることです。この列には、現行ノードのタイプ (つまり、データ型ではなくノードの種類) を返します。要素、リーフ要素、属性という 3 つのタイプについて考えてみてください。この 3 つのタイプは、以下のルールに基づいて区別されます。

  • ノードのタイプが element() で、子ノードがある場合 (./* は true に評価)、そのタイプは ELEMENT となります。
  • ノードのタイプが element() で、子ノードがない場合 (./* は false に評価)、そのタイプは LEAF-ELEMENT となります。
  • 上記のいずれにも当てはまらない場合、ノードのタイプは ATTRIBUTE となります。

上記のルールは、XML 文書にこの 3 つ以外のタイプが含まれていない場合にのみ有効であることに注意してください。XML データにコメントや処理命令が含まれているとしたら、上記のルールを拡張する必要が出てきます。

クエリー 13 を実行すると、文書内のすべての XML ノードの名前、タイプ、および値が含まれるリレーショナル・テーブルが生成されます。

TAGNAME          TYPE             VALUE
---------------- ---------------- ------------
dept             ELEMENT          -
bldg             ATTRIBUTE        101
employee         ELEMENT          -
id               ATTRIBUTE        901
name             ELEMENT          -
first            LEAF-ELEMENT     John
last             LEAF-ELEMENT     Doe
office           LEAF-ELEMENT     344
salary           LEAF-ELEMENT     55000
currency         ATTRIBUTE        USD
employee         ELEMENT          -
id               ATTRIBUTE        902
name             ELEMENT          -
first            LEAF-ELEMENT     Peter
last             LEAF-ELEMENT     Pan
office           LEAF-ELEMENT     216
phone            LEAF-ELEMENT     905-416-5004
dept             ELEMENT          -
bldg             ATTRIBUTE        114
employee         ELEMENT          -
id               ATTRIBUTE        903
name             ELEMENT          -
first            LEAF-ELEMENT     Mary
last             LEAF-ELEMENT     Jones
office           LEAF-ELEMENT     415
phone            LEAF-ELEMENT     905-403-6112
phone            LEAF-ELEMENT     647-504-4546
salary           LEAF-ELEMENT     64000
currency         ATTRIBUTE        USD

   29 record(s) selected.

クエリー 13 の結果として生成された type 列では、XML 文書にそれぞれの種類のノードがいくつ含まれるかをカウントすることもできます。このようなカウントが可能な理由は、XMLTABLE の結果はリレーショナル・テーブルであるため、SQL 演算に入力できるからです。クエリー 13count() および group by 節を追加すると、以下のクエリーになります。

クエリー 14. タイプごとの合計 XML ノード数のカウント
SELECT X."type", count(X."tagname") as count FROM test ,
XMLTABLE ('$d//(*, @*)' passing doc as "d" 
	COLUMNS 
	"tagname" VARCHAR(20) PATH  'name()',
	"type" VARCHAR(22) PATH '(if  (self::element()) 
			then (if (./*) then (''NON-LEAF ELEMENT'') else (''LEAF-ELEMENT'')) 
			else (''ATTRIBUTE''))',
	"value" VARCHAR(12)  PATH  '(.[self::element()]/text(),.[self::attribute()]/data(.))'
) AS X group by X."type"

クエリー 14 によって、以下のサマリー・テーブルが生成されます。

type         COUNT
------------ -----------
ATTRIBUTE              7
NON-LEAF ELEMENT       8
LEAF-ELEMENT          14

  3 record(s) selected.

上記の表から、データベースに保管された XML 文書に関する詳細な統計情報を簡単に見て取ることができます。XMLTABLE をベースに SQL の count() および group by 節を使用したように、XMLTABLE が生成する行セットに SQL の機能を適用することも可能です。例えば、SQL の order by 節を使えば、XMLTABLE 関数の出力をソートすることができます。


まとめ

XMLTABLE 関数は、SELECT 文および INSERT 文の中で XML データを処理する際にさまざまな用途で使えるツールです。この記事では、XMLTABLE をデプロイして大規模な XML 文書を分割する方法、簡単な XML のシュレッドを実行する方法、そして XML データのハイブリッド表現を生成する方法を説明しました。XMLTABLE をテーマとしたこの 2 回連載では、さまざまな SQL/XML 文のサンプルを記載しています。これらのサンプルをテンプレートとして使って、独自のアプリケーションを開発してください。


謝辞

この記事のレビュー、そして有益なコメントで協力してくれた Cindy Saracco 氏に感謝します。

参考文献

学ぶために

製品や技術を入手するために

  • DB2 を無料で使用するには、コミュニティー向け DB2 Express Edition の無料バージョン、DB2 Express-C をダウンロードしてください。DB2 Express Edtion と同じコア・データ機能を備えた DB2 Express-C は、アプリケーションをビルドしてデプロイするための安定した基盤になります。
  • 次期開発プロジェクトの構築に、developerWorks から直接ダウンロードできるIBM の試用版ソフトウェアをご利用ください。
  • DB2 Enterprise 9 の無料の試用版をダウンロードしてください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。プロフィールで選択した情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Information Management, XML
ArticleID=260620
ArticleTitle=XMLTABLE の例証: 第 2 回 DB2 での一般的な XMLTABLE の使用例
publish-date=09132007