本文へジャンプ

DB2 Developer Domain > 製品別技術情報 > カンタン!DB2テクテク第1歩 拡張機能編 > 

カンタン!DB2テクテク第1歩 拡張機能編

 
DB2 XMLエクステンダー-第三話

インデックス
はじめに
XMLコレクションの概要
RDB_nodeマッピングによるXML文書の分解
解説:RDB_nodeマッピングによるXML文書の分解
XML文書の構造と 表の関係
例で使用するDTDと XML文書
解説:例で使用するDTDとXML文書
XML文書分解の方式
データベースの準備
コレクション名を指定する方法
コレクション名を指定する方法 - サンプル・スクリプト
コレクション名を指定する方法 - DADファイル
コレクション名を指定する方法 - 実行結果
DAD名を指定する方法
DAD名を指定する方法 - サンプル・スクリプト

DAD名を指定する方法 - DADファイル

DAD名を指定する方法 - 実行結果
分解したXMLデータの更新
最後に
PDF(167KB)
Adobe® Reader®が必要

はじめに
前回は、XMLエクステンダーを使うための準備と、使い方の一つであるXML列の使用について見てみました。

もう一つのXML文書の保存方法であるXMLコレクションについて、今回と次回の2回にわたり見ていきたいと思います。今回は特に、XML文書の分解について見ていきましょう。

ここで示す例は製品に付属してくるsampleファイルに基づいています。

Windowsの場合、「スタート」→「プログラム」→「IBM DB2」→「コマンド・ウィンドウ」から、以下の例を実行してください。

Unixの場合、ターミナルのコマンド行から例を実行してください。


XMLコレクションの概要
XML文書の要素/属性の値のみを取り出して、リレーショナル表に保管する、またはリレーショナル表の値をもとにXML文書を合成するための一連のマッピング定義をXMLコレクションと呼びます。

DB2 XMLエクステンダーではXML文書の各要素/属性の値を取り出してリレーショナル表に保管すること(ここでは分解と呼ぶ)、およびリレーショナル表の値をXML文書の各要素/属性の値としてXML文書を組み立てること(ここでは合成と呼ぶ)の両方をサポートしています。

分解の方式には、RDB_node マッピングと呼ばれる、XML文書のロケーションパスに基づいた方式のみが使用可能です。

合成の方式には、分解と同じくRDB_node マッピングのほかに、SQL文によりどの表のどの列の値をXML文書の要素/属性の値として用いるかを指定するSQL マッピングと呼ばれる方式も使用可能です。

それぞれのマッピング方式について、分解・合成ストアド・プロシージャーの引数として、コレクション名を指定する方法とDADファイル名を直接指定する方法があります。コレクション名を指定する場合には、enable_collection コマンドであらかじめDADファイルに対応するコレクション名を登録する必要があります。

  マッピング方式 ストアド・プロシージャーーの引数
XML文書の分解 PDB_node マッピング コレクション名
DADファイル名
XML文書の合成 PDB_node マッピング コレクション名
DADファイル名
SQL マッピング コレクション名
DADファイル名


上に戻る

RDB_nodeマッピングによるXML文書の分解
XML文書の分解のシナリオ
  • 注文データであるXML文書の各要素を分解して、SALES_DBのorder_tab表、part_tab表、ship_tab表にそれぞれXML文書の要素/属性の値のみを挿入します。

  • 値に条件を設定し、その条件を満たす値のみを挿入することも可能です。

  • XML文書の各要素/属性と保管する各表・列のマッピングの定義をDADファイル内に指定します。
図1:RDB_nodeマッピングによるXML文書の分解
図1.RDB_nodeマッピングによるXML文書の分解


解説:RDB_nodeマッピングによるXML文書の分解
ここでは、以下のような条件のサンプルを考えます。
  • サービス部門用の営業データは定型のXML形式とします。

  • データベースに保管するデータは、XML文書の要素名/属性名(タグ)は含まず、値のみを保管します。
ここでは、XML文書の要素/属性の値のみを保管するために、XMLコレクション を使用してXML 文書をorder_tab表、part_tab表、ship_tab表に分解します。

値に条件を設定し、その条件を満たす値のみを挿入することも可能です。

各要素/属性とその値が保管される表・列のマッピング情報はDADファイル(neworder1.dad)内で定義されます。

このDADファイルの定義をもとに、XMLエクステンダーが提供するストアド・プロシージャーを使用して、XML文書の分解を行うことができます。

上に戻る


XML文書の構造と表の関係

図2:XML文書の構造と表の関係
図2.XML文書の構造と表の関係


例で使用するDTDとXML文書

neworder1.dtd
 
<?xml encoding="US-ASCII"?>

<!ELEMENT Order (Customer, Part+)>
<!ATTLIST Order Key CDATA #REQUIRED>
<!ELEMENT Customer (Name, Email)>
<!ELEMENT Name (#PCDATA)>
<!ELEMENT Email (#PCDATA)>
<!ELEMENT Part (Key, Quantity, ExtendedPrice, Tax, Shipment+)> 
<!ELEMENT Key (#PCDATA)>
<!ELEMENT Quantity (#PCDATA)>
<!ELEMENT ExtendedPrice (#PCDATA)>
<!ELEMENT Tax (#PCDATA)>
<!ATTLIST Part Color CDATA #REQUIRED>
<!ELEMENT Shipment (ShipDate, ShipMode, Comment?)>
<!ELEMENT ShipDate (#PCDATA)>
<!ELEMENT ShipMode (#PCDATA)>
<!ELEMENT Comment  (#PCDATA)>

neworder1.xml
 
<?xml version="1.0"?>
<!DOCTYPE Order SYSTEM "c:\dxx\dtd\neworder.dtd">

<Order Key="1">
  <Customer>
    <Name> American Motors </Name>
    <Email> parts@am.com </Email>
  </Customer >
  <Part Color="red">
    <Key>68 </Key>
    <Quantity>36 </Quantity>
    <ExtendedPrice>34850.16 </ExtendedPrice>
    <Tax>0.06 </Tax>
    <Shipment>
      <ShipDate>1998-08-19 </ShipDate>
      <ShipMode>BOAT </ShipMode>
    </Shipment>
    <Shipment>
      <ShipDate>1998-08-20 </ShipDate>
      <ShipMode>AIR </ShipMode>
    </Shipment>
  </Part>
  <Part Color="red">
    <Key>128 </Key>
    <Quantity>28 </Quantity>
    <ExtendedPrice>38000.00 </ExtendedPrice>
    <Tax>0.07</Tax>
    <Shipment>
      <!-- This shipment will not be inserted. -->
      <ShipDate>1961-01-01 </ShipDate>
      <ShipMode>BOAT </ShipMode>
    </Shipment>
    <Shipment>
      <ShipDate>1998-12-30 </ShipDate>
      <ShipMode>TRUCK </ShipMode>
    </Shipment>
  </Part>
</Order>


解説:例で使用するDTDとXML文書

「コレクション名を指定する方式」サンプル(後述)では、以下のXML文書(neworder1.xml)を使用しています。

このXML文書は、
  • Windowsの場合: (Install_Dir)\samples\xmlディレクトリ
  • Unixの場合: (Install_Dir)/samples/xmlディレクトリ
    にあります。

    (Install_Dir)はデフォルトでは
  • Windowsの場合: C:\dxx
  • AIXの場合: /usr/lpp/db2xml_07_01
  • Sunの場合: /opt/IBMdb2xml/V7.1
  • Linuxの場合: /usr/IBMdb2xml/v7.1
です。


XML文書を分解して、order_tab表、part_tab表、ship_tab表に保管します。

XML文書の要素名/属性名(タグ)は保管されません。

XML文書とリレーショナル表の列とのマッピングはDADファイル(neworder1.dad)の中で図2のように定義されています。

PRICE列に挿入する値には、「2500.00より大きい値のみ」という条件が設定されています。



XML文書分解の方式
XML 文書分解の方式には2通りの方式が用意されており、それぞれ異なるストアド・プロシージャーを使用することになります。

一つはコレクション名を指定する方式です。
  • この方式では、enable_collection コマンドによりDADファイルに対応するコレクション名を登録する必要があります。

  • コレクション名を登録するとDADファイルがXML エクステンダーの管理表内に保管されるため、XML文書を分解する際にDADファイルを指定しなくても、最初に指定したXMLコレクションの名前を指定するだけで済みます。

  • また、DADファイルに指定した表があらかじめ作成されていない場合には、enable_collection コマンドを実行した際に、XML エクステンダーによりそれらの表が自動的に作成されます。

  • dxxInsertXML ストアド・プロシージャーを使用します。

もう一つは、XML文書を分解する際に、DADファイル名を指定する方式です。
  • enable_collection コマンドを実行する必要はなく、XML文書の分解時には、コレクション名のかわりにDADファイルの内容を直接指定してストアド・プロシージャーを実行します。

  • 分解する条件が頻繁に変更される場合などには、一般的に上記の方式よりオーバーヘッドが少なくなります。

  • 分解したデータを保管する表は、分解時には存在している必要があります。

  • dxxShredXML ストアド・プロシージャーを使用します。

上に戻る


データベースの準備
サンプルファイルを実行する前に、第2話で触れました「 XML Extender を使用するための準備」の(1)〜(3)のステップを実行して、データベースの作成、バインドの実施、XML使用可能化を行う必要があります。

ここで用いるMYDBというデータベースには、データベース作成スクリプトおよびXML使用可能化のスクリプトが用意されていないので、次の手順で準備します。

MYDBの作成
  • 次のSQLコマンドを発行します。
db2 "create database MYDB"


データベースのバインドおよびMYDBのXML使用可能化
  • 第2話で用いたgetstart_prep.cmdを利用します。元のgetstart_prep.cmdファイルの中で、データベース名にSALES_DBと指定されていた部分をMYDBに修正して実行します。
 
db2 "connect to MYDB"

cd /d %DB2DXXPATH%\bnd
db2 "bind @dxxbind.lst"
cd /d %DB2PATH%\bnd
db2 "bind @db2cli.lst"

db2 "terminate"

cd /d %DB2DXXPATH%\samples\cmd  
dxxadm enable_db MYDB
MYDB : この2ヶ所をSALES_DBからMYDBに修正します


コレクション名を指定する方法
まずは、コレクション名を指定するサンプルを見てみましょう。

コレクション名を指定するサンプルは、insertxml.cmd サンプル・ファイルに記述されています。

insertxml.cmd内では、以下のステップが実行されます。
  1. 分解するXMLファイルの妥当性検査を行う場合(DADファイル内でvalidationをYESに指定した場合)は、使用するDTDファイル(neworder1.dtd)をDTD_REF表に挿入します。

  2. enable_collection コマンドをDADファイルを指定して実行し、XMLコレクションに名前をつけて XMLコレクションを登録します。この際に分解するデータを格納する表がXMLエクステンダーにより自動的に作成されます。ここでは、neworder1.dadファイルを指定し、XMLコレクションに「abc」という名前をつけて登録しています。

  3. dxxInsertXML ストアド・プロシージャーを使用してXML文書の分解を行います。
    実際には、内部でdxxInsertXMLストアド・プロシージャーを使用するinsertxというプログラムを使用して、XML文書の分解・MYDBへの挿入を行っています。insertxプログラムの内容は以下のファイルで確認できます。
      Windowsの場合: (Install_Dir)\samples\c\insertx.sqx
      Unixの場合: (Install_Dir)/samples/c/insertx.sqx

  4. 分解したデータを確認するために、SELECT文により表の内容を確認します。

  5. 作成した表をドロップし、DTDファイルのエントリを削除して、作成した環境を削除します。

  6. disable_collection コマンドにより、XMLコレクションの登録を削除します。
ここで使用するDADファイルは以下のファイルになります。
  • Windowsの場合: (Install_Dir)\samples\dad\neworder1.dad
  • NIXの場合: (Install_Dir)/samples/dad/neworder1.dad

上に戻る


コレクション名を指定する方法−サンプル・スクリプト

insertxml.cmd ファイルの内容(Windows版)
 
@echo off
rem 
rem   insertxml -- test dxxInsertXML() for partial decomposition
rem 

db2  "connect to mydb"

db2 "insert into db2xml.dtd_ref values('neworder.dtd',
db2xml.XMLClobFromFile
('%DB2DXXPATH%\samples\dtd\neworder.dtd'), 0, 'anita', 'anita','anita')" ←a db2 "echo -------- Enabling collection abc. --------" dxxadm enable_collection mydb abc %DB2DXXPATH%\samples\dad\neworder1.dad ←b db2 "echo -------- Calling the dxxInsertXML stored procedure. --------" insertx mydb abc %DB2DXXPATH%\samples\xml\neworder1.xml ←c db2 "select * from order_tab" db2 "select * from part_tab" ←d db2 "select * from ship_tab" db2 "echo -------- Cleaning up the database mydb. --------" ←e db2 drop table order_tab db2 drop table part_tab db2 drop table ship_tab dxxadm disable_collection mydb abc ←f db2 "delete from db2xml.dtd_ref where dtdid='neworder.dtd'" db2 terminate


コレクション名を指定する方法−DADファイル

neworder1.dad ファイルの内容(Windows版:抜粋)
   
<?xml version="1.0"?> 
<!DOCTYPE DAD SYSTEM "c:\dxx\dtd\dad.dtd">
<DAD>
  <validation>NO</validation>
  <Xcollection> 
  <prolog>?xml version="1.0"?</prolog> 
  <doctype>!DOCTYPE Order SYSTEM 
"c:\dxx\samples\dtd\neworder.dtd"
</doctype> <root_node> <element_node name="Order"> <RDB_node> <table name="order_tab" key="order_key"/> <table name="part_tab" key="part_key"/> <table name="ship_tab" key="ship"/> <condition> order_tab.order_key=part_tab.o_key AND
part_tab.part_key=ship_tab.p_key </condition> </RDB_node> <attribute_node name="Key"> <RDB_node> <table name="order_tab"/> <column name="order_key" type="integer"/> </RDB_node> </attribute_node> <element_node name="Customer"> <element_node name="Name"> <text_node> <RDB_node> <table name="order_tab"/> <column name="customer_name"
type="varchar(16)"/> </RDB_node> </text_node> </element_node>









分解する表の定義














Name要素のマッピング定義 

上に戻る


コレクション名を指定する方法−実行結果
insertxml.cmdの実行結果より、元となるXML文書が分解されてリレーショナル表に格納されたことを見ることができます。

db2 "select * from order_tab"
 
ORDER_KEY	CUSTOMER_NAME     CUSTOMER_EMAIL
-----------	----------------- ----------------
          1 American Motors   parts@am.com

db2 "select * from part_tab"
 
COLOR   PART_KEY    PRICE     TAX            QTY        O_KEY
------- ----------- --------- -------------- ---------  -----------
red              68  34850.16  +6.00000E-002        36            1 
red             128  38000.00  +7.00000E-002        28            1


db2 "select * from ship_tab"
 
SHIP                                             P_KEY
------------------------------------------------ -------------------------------
< Shipment >
      < ShipDate > 1998-08-19 < /ShipDate >
      < ShipMode > BOAT < /ShipMode >
    < /Shipment >
                                                  68
< Shipment >
      < ShipDate > 1998-08-20 < /ShipDate >
      < ShipMode > AIR < /ShipMode >
    < /Shipment >
                                                  68

(後略)



DAD名を指定する方法
DADファイル名を指定するサンプルは、shredxml.cmd サンプル・ファイルに記述されています。

サンプル・ファイル内では、以下のステップが実行されます。

  1. 分解したデータを保管するための表(order_tab表、part_tab表、ship_tab表)を作成します。これらの表は分解するストアド・プロシージャーを実行する前に作成しておかなくてはなりません。また、表の列名、列の数、データタイプなどはDADファイル内の指定と一致していなくてはなりません。

  2. dxxShredXML ストアド・プロシージャーを使用してXML文書の分解を行います。引数に指定するのはDADファイルと分解するXML文書の名前です。
    実際には、内部でdxxShredtXMLストアド・プロシージャーを使用するshredというプログラムを使用して、XML文書の分解・MYDBへの挿入を行っています。shredプログラムの内容は以下のファイルで確認できます。
      Windowsの場合: (Install_Dir)\samples\c\shred.sqx
      Unixの場合: (Install_Dir)/samples/c/shred.sqx

  3. 分解したデータを確認するために、SELECT文により表の内容を確認します。

  4. 作成した表をドロップして、作成した環境を削除します。
ここで使用するDADファイルは以下のファイルになります。
  • Windowsの場合: (Install_Dir)\samples\dad\neworder2.dad
  • UNIXの場合: (Install_Dir)/samples/dad/neworder2.dad
上に戻る


DAD名を指定する方法−サンプル・スクリプト

shredxml.cmd ファイルの内容(Windows版)
 
@echo off
rem  
rem  shredxml -- test dxxShredXML for composite primary and foreign keys
rem             for existing tables.
rem
db2 "connect to mydb" db2 "echo -------- Setting up the database mydb. --------" ←a db2 "create table order_tab(order_key1 integer, order_key2
integer, order_key3 integer, customer_name
varchar(16), customer_email varchar(16))" db2 "create table part_tab(part_key1 integer,
part_key2 integer, color char(6), qty integer, price
decimal(10,2), tax real, o_key1 integer, o_key2 integer, o_key3 integer)" db2 "create table ship_tab(date date, mode char(6),
comment varchar(128), p_key1 integer, p_key2 integer)" db2 "echo -------- Calling the dxxShredXML
stored procedure. --------" shred mydb %DB2DXXPATH%\samples\dad\neworder2.dad
%DB2DXXPATH%\samples\xml\neworder2.xml ←b db2 "echo -------- Displaying the result of the decomposition. --------" db2 "select * from order_tab" db2 "select * from part_tab" db2 "select * from ship_tab" ←c db2 "echo -------- Cleaning up the database mydb. --------" db2 "drop table order_tab" db2 "drop table part_tab" ←d db2 "drop table ship_tab" db2 "terminate"


DAD名を指定する方法−DADファイル

neworder2.dad ファイルの内容(Windows版:抜粋)
   
<?xml version="1.0"?>  
<!DOCTYPE DAD SYSTEM "c:\dxx\dtd\dad.dtd">  
<DAD> 
  <dtdid> neworder2.dtd</dtdid>  
  <validation> NO</validation>  
  <Xcollection>  
 <prolog> ?xml version="1.0"?</prolog> 
 <doctype> !DOCTYPE Order SYSTEM 
"c:\dxx\samples\dtd\neworder2.dtd"</doctype> <root_node> <element_node name="Order"> <RDB_node> <table name="order_tab"
key="order_key1 order_key2 order_key3"/> <table name="part_tab"
key="part_key1 part_key2"/> <table name="ship_tab" key="date"/> <condition> order_tab.order_key1=part_tab.o_key1 AND order_tab.order_key2=part_tab.o_key2 AND order_tab.order_key3=part_tab.o_key3 AND part_tab.part_key1=ship_tab.p_key1 AND part_tab.part_key2=ship_tab.p_key2 </condition> </RDB_node> <attribute_node name="Key1"> <RDB_node> <table name="order_tab"/> <column name="order_key1" type="integer"/> </RDB_node> </attribute_node> <attribute_node name="Key3"> <RDB_node> <table name="order_tab"/> <column name="order_key3" type="integer"/> </RDB_node> </attribute_node>












分解する表の定義 









Key1属性のマッピング定義 







Key3属性のマッピング定義 

上に戻る


DAD名を指定する方法−実行結果
shredxml.cmdの実行結果より、元となるXML文書が分解されてリレーショナル表に格納されたことを見ることができます。

db2 "select * from order_tab"
 
ORDER_KEY	CUSTOMER_NAME     CUSTOMER_EMAIL
-----------	----------------- ----------------
          1 American Motors   parts@am.com

db2 "select * from part_tab"
 
COLOR   PART_KEY    PRICE     TAX            QTY        O_KEY
------- ----------- --------- -------------- ---------  -----------
red              68  34850.16  +6.00000E-002        36            1
red             128  38000.00  +7.00000E-002        28            1

db2 "select * from ship_tab"
 
DATE       MODE   COMMENT         P_KEY1      P_KEY2
---------- ------ ------------ ----------- ---------- 
1998-08-19 BOAT   -               68         8
1998-08-20 AIR    -               68         8
1998-12-30 TRUCK  -               128  88888888


分解したXMLデータの更新
XMLエクステンダー でXMLデータを分解して表に格納した後、そのデータの一部を更新することを考えます。

XMLエクステンダー のストアド・プロシージャーでは、一度分解したデータを更新する機能を提供していません。

分解後のデータはDB2の表の形式で保管されているので、SQL文を使用して更新操作をすることになります。

あるいは、更新したいXMLデータに該当するデータをSQL文を使用して表からすべて削除し、
新たに表にデータを挿入(つまり、XMLエクステンダー のストアド・プロシージャーによる分解)を行うことで対処することも可能です。


最後に
今回はXMLコレクションを用いて、XML文書を分解した上で各データ要素をリレーショナル表に保管する方法を見てきました。
この方法ですと、XML文書の内容を他のアプリケーションでも利用したいときに、データを扱いやすいという利点があります。

次回は、データ要素に分解して保管されたXMLコレクションから、再度、XML文書を合成する方法について、見ていきたいと思います。

上に戻る