 |
DB2 Developer
Domain > 製品別技術情報 > カンタン!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文書の分解
解説:RDB_nodeマッピングによるXML文書の分解
ここでは、以下のような条件のサンプルを考えます。
- サービス部門用の営業データは定型のXML形式とします。
- データベースに保管するデータは、XML文書の要素名/属性名(タグ)は含まず、値のみを保管します。
ここでは、XML文書の要素/属性の値のみを保管するために、XMLコレクション を使用してXML 文書をorder_tab表、part_tab表、ship_tab表に分解します。
値に条件を設定し、その条件を満たす値のみを挿入することも可能です。
各要素/属性とその値が保管される表・列のマッピング情報はDADファイル(neworder1.dad)内で定義されます。
このDADファイルの定義をもとに、XMLエクステンダーが提供するストアド・プロシージャーを使用して、XML文書の分解を行うことができます。
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の作成
| 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内では、以下のステップが実行されます。
- 分解するXMLファイルの妥当性検査を行う場合(DADファイル内でvalidationをYESに指定した場合)は、使用するDTDファイル(neworder1.dtd)をDTD_REF表に挿入します。
- enable_collection コマンドをDADファイルを指定して実行し、XMLコレクションに名前をつけて XMLコレクションを登録します。この際に分解するデータを格納する表がXMLエクステンダーにより自動的に作成されます。ここでは、neworder1.dadファイルを指定し、XMLコレクションに「abc」という名前をつけて登録しています。
- dxxInsertXML ストアド・プロシージャーを使用してXML文書の分解を行います。
| * |
実際には、内部でdxxInsertXMLストアド・プロシージャーを使用するinsertxというプログラムを使用して、XML文書の分解・MYDBへの挿入を行っています。insertxプログラムの内容は以下のファイルで確認できます。 |
| |
Windowsの場合: (Install_Dir)\samples\c\insertx.sqx |
| |
Unixの場合: (Install_Dir)/samples/c/insertx.sqx |
- 分解したデータを確認するために、SELECT文により表の内容を確認します。
- 作成した表をドロップし、DTDファイルのエントリを削除して、作成した環境を削除します。
- 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 サンプル・ファイルに記述されています。
サンプル・ファイル内では、以下のステップが実行されます。
- 分解したデータを保管するための表(order_tab表、part_tab表、ship_tab表)を作成します。これらの表は分解するストアド・プロシージャーを実行する前に作成しておかなくてはなりません。また、表の列名、列の数、データタイプなどはDADファイル内の指定と一致していなくてはなりません。
- dxxShredXML ストアド・プロシージャーを使用してXML文書の分解を行います。引数に指定するのはDADファイルと分解するXML文書の名前です。
| * |
実際には、内部でdxxShredtXMLストアド・プロシージャーを使用するshredというプログラムを使用して、XML文書の分解・MYDBへの挿入を行っています。shredプログラムの内容は以下のファイルで確認できます。 |
| |
Windowsの場合: (Install_Dir)\samples\c\shred.sqx |
| |
Unixの場合: (Install_Dir)/samples/c/shred.sqx |
- 分解したデータを確認するために、SELECT文により表の内容を確認します。
- 作成した表をドロップして、作成した環境を削除します。
ここで使用する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文書を合成する方法について、見ていきたいと思います。
|
|
|