目次


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

DB2 XMLエクステンダー:第3話

Comments

コンテンツシリーズ

このコンテンツは全#シリーズのパート#です: カンタン!DB2テクテク第1歩 拡張機能編

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:カンタン!DB2テクテク第1歩 拡張機能編

このシリーズの続きに乞うご期待。

はじめに

前回は、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文書の分解
A typical Web architecture
A typical Web architecture

解説: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文書の構造と表の関係
図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

です。

MXML文書を分解して、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>                     Name要素のマッピング定義 </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>

コレクション名を指定する方法−実行結果

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. enable_collection コマンドをDADファイルを指定して実行し、XMLコレクションに名前をつけて XMLコレクションを登録します。この際に分解するデータを格納する表がXMLエクステンダーにより自動的に作成されます。ここでは、neworder1.dadファイルを指定し、XMLコレクションに「abc」という名前をつけて登録しています。
  3. dxxInsertXML ストアド・プロシージャーを使用してXML文書の分解を行います。
    実際には、内部でdxxShredtXMLストアド・プロシージャーを使用するshredというプログラムを使用して、XML文書の分解・MYDBへの挿入を行っています。shredプログラムの内容は以下のファイルで確認できます。
    Windowsの場合: (Install_Dir)\samples\c\insertx.sqx
    Unixの場合: (Install_Dir)/samples/c/insertx.sqx
  4. 分解したデータを確認するために、SELECT文により表の内容を確認します。
  5. 作成した表をドロップして、作成した環境を削除します。

ここで使用する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"> Key1属性のマッピング定義 <RDB_node> <table name="order_tab"/> <column name="order_key1" type="integer"/> </RDB_node> </attribute_node> <attribute_node name="Key3"> Key1属性のマッピング定義 <RDB_node> <table name="order_tab"/> <column name="order_key3" type="integer"/> </RDB_node> </attribute_node>

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文書を合成する方法について、見ていきたいと思います。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Information Management
ArticleID=321448
ArticleTitle=カンタン!DB2テクテク第1歩 拡張機能編: DB2 XMLエクステンダー:第3話
publish-date=11302005