連載 DB2でXMLを操作する(4)
XML ColumnにDocBook文書を格納する

XMLの普及とともにリレーショナルデータベースにもXMLを格納できる機能が搭載されてきている。しかしその機能は、製品ごとに固有のものだ。この記事では、IBMの製品であるDB2 UDBでどのようにXMLを扱うか、について解説する。

たがわ製作所
2003/4/18


今回の主な内容
DocBookをサンプル文書に
XML Columnを用いるための設計作業
XML Columnを用いるための実装作業
XML文書の挿入
XML文書の検索
XML文書の削除
XML文書の更新
[応用編]サイドテーブルを用いないXML文書の検索
[応用編]XML文書の部分更新

 前回「XML Columnを使うための設計・実装」では、DB2でXMLを取り扱うための手段の1つであるXML Columnの利用手順について概説しました。今回はXML Columnのサンプルを取り上げ、その具体的な利用例を解説してみたいと思います。また、前回は解説できなかった、XML Columnに格納されているXML文書の利用方法についても解説します。

DocBookをサンプル文書に

 前回でもおさらいしましたが、XML ColumnはXML文書をCLOBのデータとしてカラムにそのまま格納するアプローチです(第1回「XMLの格納方法を2種類備えるDB2」参照)。XML文書をそのままの形で保存しておきたいようなデータがその適用の候補となるわけですが、今回はそのような例としてDocBook形式のXML文書を取り上げたいと思います。

 DocBookはテクニカル文書の作成によく用いられる文書フォーマットで、現在はOASISで標準化されています。もともとはSGMLで利用されていたフォーマットですが、現在ではXMLのDTDも用意されています。ソフトウェアのマニュアルなどで利用されていることもあるため、名前を聞いたことがある読者もおられるのではないでしょうか。少し手前ミソですが、実は本連載の原稿もDocBookの形式のXML文書の形で執筆しています。筆者はもともとプレーンテキストの形式で原稿を書いていたのですが、最近はもっぱらDocBookの形式で執筆するようになりました。今回は、そのおかげで潤沢(?)に存在する文書の一部をサンプルとして実際に利用しようという魂胆です。

 そこで、この連載のいままでの原稿(第1回〜第3回)をサンプルとして用いることにしました。とはいえ、そのままではさすがに取り扱いが煩雑になるので、最初のパラグラフのみを取り出して簡略化してあります。

<?xml version="1.0" encoding="Shift_JIS" ?>
<!DOCTYPE article SYSTEM "sample.dtd">


<article>
  <title>
    DB2でXMLを操作する(1) 〜 XMLの格納方法を2種類備えるDB2
  </title>


  <articleinfo>
    <author>たがわ製作所</author>
    <keywordset>
      <keyword>XML</keyword>
      <keyword>DB2</keyword>
      <keyword>XQuery</keyword>
      <keyword>Xperanto</keyword>
    </keywordset>
  </articleinfo>


  <section>
    <title>はじめに</title>
    <para>
      この連載は、DB2 Universal Database(以下DB2)を用いたXML文書の管理について解説するものです。DB2は皆さんもご存知のとおり、IBMによって開発された25年の歴史を持つRDBMSです。大きいところではホストから、小さいところはPDAまでと幅広いプラットフォームをサポートしています。2002年10月現在時点での最新バージョンは7.2であり、近々8.1がリリースされる予定です。
    </para>
  </section>


</article>
リスト1 DocBook形式のXML文書のサンプル
今回は、この形式のサンプル文書を3種類用意してある。上記はarticle1.xmlを表示したもの。それほど複雑な形式ではないことが分かる(article1.xmlarticle2.xmlarticle3.xml

 説明の必要はほとんどないかと思いますが、簡単に解説しておきます。文書のルートタグは<article>です。以下、タイトルを示す<title>、そのほかのメタ情報を表す<articleinfo>と続き、<articleinfo>には作者名<author>とキーワード<keywordset>が含まれています。

 今回は、これらの文書を格納することはもちろんですが、これらの文書を検索し、その結果に基づいて削除したり更新したりすることに挑戦してみます。早速実際の作業に取り掛かってみることにしましょう。前回の内容に沿って、XML Columnを用いるための設計作業、それに続いて実装作業という形で進めることにします。

XML Columnを用いるための設計作業

 前回「XML Columnを使うための設計・実装」では、XML Columnを利用するためにいくつか事前のデータ設計が必要であることを紹介しました。それにならって進めていきます。

(1)設計作業の概要

 設計作業で検討する内容は次のようなものでした。

  1. XMLデータタイプ
  2. 文書型の検証の有無
  3. インデックス対象の要素および属性
  4. サイドテーブルの構成
  5. デフォルトビューの有無

 以下、順にこれらの内容について検討してみます。

(2)XMLデータタイプ

 まずXML文書を格納するためのカラムのデータ型を決定します。このデータ型として利用できるものには以下の3種類がありました。

  • XMLVARCHAR (32767bytesまで格納可能)
  • XMLCLOB (2Gbytesまで格納可能)
  • XMLFILE (ファイルシステム上に格納)

 今回はどのデータ型を使うべきでしょうか? データをカラムに格納したいことを考えると、XMLFILEは自然と候補から外れます。あとはXMLVARCHARかXMLCLOBか、ということになります。DocBook形式の文書を格納して文書データベースとして運用することを考えると、データサイズの点からXMLCLOBを採用することになるでしょう。ただしCLOBデータを採用する場合は、テーブルスペースを分離する、サイズによってはログを取らないようにする、などの考慮が必要になってくるので注意してください。もちろんこれはXML文書を取り扱う場合に限定される話でなく、DB2でCLOBデータを取り扱う場合一般の話ですので、詳細は割愛します。

 今回はサンプルということで、手軽に使えるXMLVARCHARを採用したいと思います。データのサイズもそれほど大きくないので問題はありません。取りあえずXMLVARCHARを採用するとして、実際のテーブルの構成は以下のようにしてみました。

XML文書を格納するためのテーブル articles
カラム名 データ型
id INT
article XMLVARCHAR

(3)文書型の検証の有無

 今回のサンプルで取り扱うデータはDocBook形式のXML文書です。何がしかのオーサリングツールを利用することもありえますが、人間がエディタを用いて作成する場合も多いでしょう。これを踏まえると、今回はXML文書をデータで格納する前に文書型の検証を行った方がよさそうです。

 検証を行うためにはDTDが必要です。実際のDocBookのDTDは少し大きいので、今回はこのサンプルに合わせて簡略化したものを用意しました。こちらは詳しく解説しませんが、実際の文書と見比べてみれば一目瞭然でしょう。

<!ELEMENT article (title, articleinfo, (section)+)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT articleinfo (author, keywordset)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT keywordset (keyword)+>
<!ELEMENT keyword (#PCDATA)>
<!ELEMENT section (title, (para)+)>
<!ELEMENT para (#PCDATA)>
リスト2 サンプルDocBookのDTD
実際のDocBookのDTDはもっと複雑だが、これはサンプル用に簡略化してある(sample.dtd

(4)インデックス対象の要素および属性

 前回も解説しましたが、XML Columnでは頻繁に検索の対象となるカラムをサイドテーブルに抽出して利用します。今回は取り上げるサンプルがDocBook形式のXML文書ということなので、以下を検索対象とすることにします。

  • タイトル
  • 作者名
  • キーワード
(5)サイドテーブルの構成

 検索対象が決まったので、それに基づいてサイドテーブルの構成を決めます。今回検索対象とするのは、タイトル、作者名およびキーワードです。これらのうち、キーワードについては1つの文書に対して複数存在し得る点に注意してください。このような検索対象は、独立した1つのサイドテーブルに分離する必要がありました。これを踏まえて、サイドテーブルは以下のような構成にすることとします。

サイドテーブルの構成
テーブル名 含める検索対象
side_articles タイトル、作者
side_articles_keywords キーワード

(6)デフォルトビューの有無

 XML Columnを利用する場合、XML文書を格納したテーブルとサイドテーブルを結合したデフォルトビューが利用できました。今回はせっかくですからこのデフォルトビューも利用(作成)することにしましょう。このデフォルトビューは、もともとのテーブルと2つのサイドテーブルを結合したものになります。

XML Columnを用いるための実装作業

(1)実装作業の概要

 これも前回解説したとおり、実装作業は以下の手順で行います。

  1. DADファイルの定義
  2. XMLエクステンダーの有効化
  3. テーブルを作成
  4. DTDの登録
  5. DADファイルの登録およびXML Columnの有効化
  6. インデックスの作成

 以下、この流れに沿って実装の作業を進めてみます。

(2)DADファイルの定義

 ここまで設計した内容に基づいてDADを定義します。

<?xml version="1.0" encoding="UTF-8"?>
<dad>

  <dtdid>sample.dtd</dtdid>
  <validation>yes</validation>


  <Xcolumn>

    <table name="side_articles">
      <column name="title"
        type="VARCHAR(256)"
        path="/article/title"
        multi_occurrence="no" />
      <column name="author"
        type="VARCHAR(256)"
        path="/article/articleinfo/author"
        multi_occurrence="no" />
    </table>


    <table name="side_articles_keywords">
      <column name="keyword"
        type="VARCHAR(256)"
        path="/article/articleinfo/keywordset/keyword"
        multi_occurrence="yes" />
    </table>

  </Xcolumn>


</dad>
リスト3 設計内容に基づいて定義したDAD
データタイプ、文書型検証の有無などの設計内容をDB2に知らせるために使うのがDADファイル。XML文書形式で記述する(sample.dad

 DADファイルの内容について、以下の点を順に確認してみてください。

  • 文書型の検証を行うように<validation>でyesを指定している
  • 文書型の検証で用いるDTDの名前をsample.dtdとしている
  • 2つのサイドテーブルを<table>で定義している
  • 各サイドテーブルに含まれるカラムを<column>で指定している
  • 2つ目のサイドテーブルの属性multi_occurrenceでyesを指定している

 特に注意したいのは、サイドテーブルに含まれるカラムの定義をしている部分です。詳しくは解説はしませんが、検索対象としているロケーションパス(path)、その型(type)がどのように指定されているか確認してみてください。また繰り返しになりますが、2つ目のサイドテーブルの定義でmulti_occurrenceがyesに指定されている点にも注意してください。

(3)XMLエクステンダーの有効化

 ではいよいよ実際にXML文書のデータベースを作っていきましょう。入れ物となるデータベースが必要ですが、今回はインストール時に作成したサンプルデータベースsampleをそのまま利用することにします(詳しくは連載の第2回「DB2 UDBのインストールと動作確認」を参照)。

 まずはデータベースに接続してください。

db2 connect to sample

 XMLエクステンダーのツールを利用できるようにバインドを実行します。DB2をインストールしたディレクトリの下にあるbndというディレクトリに移動して以下のコマンドを実行します。

db2 bind @dxxbind.lst

 次にデータベースでXMLエクステンダーの機能(ユーザ定義型、ユーザ定義関数など)を利用できるよう、有効化の作業を行います。

dxxadm enable_db sample

 このあたりの手順は前回解説したとおりです。画面1に実行例を示しておきます。

画面1 データベースの有効化の実行例

(4)テーブルを作成

 データベースが用意できたので、設計した内容に基づいてXML文書を格納するためのテーブルを定義します。

create table articles (id int, article DB2XML.XMLVARCHAR)

 XMLデータタイプであるXMLVARCHAR型を用いるときに、スキーマ名DB2XMLで修飾している点に注意してください。

(5)DTDの登録

 DADファイルを登録してXML Columnの有効化を行う前に、DADファイルで参照しているDTDのファイルを登録します。先ほど準備したサンプルのDTDファイルをsample.dtdという名前で登録します(この名前は先ほどのDADファイルで定義したものです)。

db2 insert into db2xml.dtd_ref values ('sample.dtd', DB2XML.XMLClobFromFile('c:\sample\sample.dtd'), 0, 'user', 'user', 'user')

 DTDファイルへのパスはフルパスで正しく指定する必要があるので注意してください。ここではc:\sampleにdtdファイルがあると仮定しています。

(6)DADファイルの登録およびXML Columnの有効化

 DTDの登録が終わったので、ようやくXML Columnを有効化する作業が可能になりました。この有効化の作業はdxxadmコマンドで行います。

dxxadm enable_column sample articles article c:\sample\sample.dad -v articles_by_index

 enable_columnの引数で、データベース名、テーブル名、カラム名、DADファイルへのパスを順に指定しています(ここではc:\sampleにDADファイルがあると仮定しています)。また、今回はデフォルトビューを作成するので、その名前articles_by_indexを-vオプションで指定しています。

(7)インデックスの作成

 以上でXML Columnは利用できるようになりました。最後に、サイドテーブルにインデックスを作成しておきましょう。ここでは、各サイドテーブルのカラムごとにインデックスを作成しておきます。

db2 create index index_title on side_articles (title)
db2 create index index_author on side_articles (author)
db2 create index index_keyword on side_articles_keywords (keyword)

 ここまでの手順の実行例を画面2に示します。

画面2 テーブルの作成からインデックスの作成までの実行例

 以上でXML Columnの利用準備が終わりました。とはいえ、これだけでは単にXML文書の入れ物ができただけの話です。次は、XML文書を保存する、XML文書を検索するなどの基本的な操作について見ていきましょう。

XML文書の挿入

 まずはデータベースにXML文書を挿入する作業から解説していきます。挿入は非常に簡単で、以下のようにInsert文を用いてデータを挿入するだけです。

insert into articles (id, article) values (キーの値, DB2XML.XMLVarcharFromFile('保存するXML文書のパス'))

 ポイントはXMLVARCHARのカラムに挿入する値の指定方法です。ここではXMLエクステンダーのUDFの1つである、XMLVarcharFromFileを用いています。この関数は、ファイルの内容を読んでVARCHARの値として返すもので、ほかのバリエーションとしてはXMLClobFromFileなどがあります。このUDFを利用する際は、挿入するXML文書のパスをフルパスで正しく指定する必要があるので注意してください。

 今回用意した3つのサンプルを挿入しておきましょう。コマンドラインプロセッサを立ち上げて以下のSQLを実行してみてください(ここではサンプルのファイルがc:\sampleにあるものと仮定しています)。

insert into articles (id, article) values (1, DB2XML.XMLVarcharFromFile('c:\sample\article1.xml'))
insert into articles (id, article) values (2, DB2XML.XMLVarcharFromFile('c:\sample\article2.xml'))
insert into articles (id, article) values (3, DB2XML.XMLVarcharFromFile('c:\sample\article3.xml'))

XML文書の検索

 次に挿入したXML文書を検索する方法について見ていきましょう。まず、タイトルに'XML Column'という文字列が含まれている文書を検索するという例を取り上げてみます。

select article from articles a, side_articles b where a.dxxroot_id = b.dxxroot_id and title like '%XML Column%'

 見ていただければ分かるように、元のテーブルとサイドテーブルを結合した後、サイドテーブルの値で検索条件を指定しているだけです。いちいち結合するのが面倒ですが、このような場合はデフォルトビューを用いると簡単です。

select distinct article from articles_by_index where title like '%XML Column%'

 デフォルトビューでは、元のテーブルと2つのサイドテーブルを結合しています。サイドテーブルの1つ、side_articles_keywordsには、1つの文書に対応する複数のキーワードが含まれています。デフォルトビューではこのテーブルも結合していますから、同じarticleを含む行が複数存在することになります。単純にSelectするだけだとこれらの同じ行が繰り返し出てきますから、上の例ではDistinctを指定して重複しているものを取り除いています。

 このようにデフォルトビューは単純にすべてのサイドテーブルを結合して定義してしまうため、実際の検索を行う場合は少し注意が必要になってきます。またサイドテーブルの個数が増えてくる場合はパフォーマンスにも影響してきますから、実際には皆さんの手で必要なビューを定義することをお勧めします。

 さて、ここまでの例は、XMLVARCHARのカラムを単純に選択しただけでした。時と場合によっては、XML文書すべてでなく、そのうちの一部を取り出したいこともあるでしょう。このような場合は、XMLエクステンダーに含まれるUDFを利用することができます。

select distinct DB2XML.extractVarchar(article, '/article/section/title') from articles_by_index where title like '%XML Column%'

 この例では、extractVarcharというUDFを利用して、文書からセクションのタイトルを取り出しています。このUDFは、指定したロケーションパスの値をVARCHAR型の値として抽出するもので、ほかのバリエーションとしてextractIntegerやextractClobなどがあります。必要に応じて適宜使い分ければよいでしょう。

 なお、実際に上記の検索を実行してみればお分かりかと思いますが、選択したCLOBもしくはVARCHARのカラムの長さが非常に長く、確認しづらいかもしれません。このような場合はSUBSTR関数を用いて適当に長さを短くして確認するとよいでしょう。

select distinct SUBSTR(DB2XML.extractVarchar(article, '/article/section/title'), 1, 32) from articles_by_index where title like '%XML Column%'

 SUBSTRを利用して検索を実行してみた例を画面3に示します。

画面3 SUBSTRを利用した検索の実行例

XML文書の削除

 次は挿入した文書を削除する方法について見てみます。削除も基本的に普通の行の削除と同じくDeleteを用いるだけです。ポイントは削除行の指定方法です。Delete文は文法的に1つのテーブルを指定して削除の条件を指定する形式になっています。プライマリキーを指定してXML文書を削除する(今回であればidの値を指定する)ような場合は以下のように書けるので問題ないでしょう。

delete from articles where id = 1

 しかし、このように削除できる行をあらかじめ特定できている場合ばかりとは限りません。実用を考えれば、サイドテーブルの値に基づいて削除したい場合もあり得ます。このような場合は、以下のように副照会を用いる方法が考えられます。

delete from articles where id in (select id from articles_by_index where title like '%XML Column%')

XML文書の更新

 更新も削除の場合と同じように考えます。元のテーブルの値のみで行を指定できる場合は通常の行のUpdateと同じですし、サイドテーブルの値に基づいて行を指定する場合は副照会を用います。

update articles set article = DB2XML.XMLVarcharFromFile('更新内容を保存したファイルへのパス') where id in (select id from articles_by_index where title like '%XML Column%')

 以上、基本的な操作方法について見てきました。これだけでもかなりのことができるはずですが、以下ではさらに応用的な操作について触れておきたいと思います。

[応用編]サイドテーブルを用いないXML文書の検索

 先ほど照会した検索の例は、サイドテーブルの値を用いて検索するやり方でした。検索要件が分かっている場合はサイドテーブルを作成するのも容易ですが、必ずしもそういう場合ばかりとは限りません。時間はある程度かかってもよいので、サイドテーブルに含まれないロケーションの値で検索したいということもあるでしょう。

 もちろんこのような検索も可能です。察しのよい方はすでに想像がついているかと思いますが、このような検索には先ほど登場したUDFを用います。

select article from articles where DB2XML.extractVarchar(article, 'title') like '%XML Column%'

 見ればすぐに分かりますが、先ほどXML文書から特定のロケーションの値を取り出すのに用いたUDF、extractVarcharを条件節で使用しているだけです。以上は検索の例ですが、削除、更新の条件指定についても同じようにできるはずです。

[応用編]XML文書の部分更新

 次は部分更新です。先ほど紹介した更新の例は、文書全体を更新するものでした。時には文書の一部のみ更新したい場合もあるでしょう。このような場合は、updateというXMLエクステンダーのUDFを利用します(紛らわしいですがSQLのUpdateとは別のものです)。

update articles set article = DB2XML.update(article, '/article/title', 'タイトル未定') where id = 10

 この例で用いられているDB2XML.updateは、指定したXML文書のロケーションの値を更新し、更新後のXML文書を返すものです。この例では簡略化のために条件指定は簡単なものにしていますが、ほかのやり方で条件を指定した場合も同様です。

 上記の例ではXML文書の/article/titleの値を'タイトル未定'に変更しています。ここで思い出していただきたいのですが、この/article/titleはサイドテーブルに検索対象として抽出しているロケーションです。つまりこの/article/titleというロケーションの値はサイドテーブルに抽出されているはずなのですが、いまDB2XML.updateを用いて元の文書の値を変更してしまいました。

 皆さんに実際に確認していただきたいのですが、サイドテーブルの値はどうなっているでしょうか? Selectで照会してみればすぐに分かることですが、上記のSQLでの変更を受けて、サイドテーブルの値は自動的に書き換えられているはずです。

 今回は前回紹介したXML Columnの利用手順を踏まえ、DocBook形式のXML文書をXML Columnで操作する例を紹介しました。取り扱った文書はサンプルということで簡略化してありますが、XML Columnの実用性について実感していただけたのではないかと思います。XML文書をそのまま保存し、検索や更新をするような要求がある場合にぜひ適用してみてください。

 次回は、DB2でXMLを扱うためのもう1つの方法、XML Collectionの利用手順について概説したいと思います。お楽しみに!

<<前回へ 「XML Collectionを使うための設計・実装」

Index
連載:DB2でXMLを操作する
  (1) XMLの格納方法を2種類備えるDB2
  (2) DB2 UDBのインストールと動作確認
  (3) XML Columnを使うための設計・実装
(4) XML ColumnにDocBook文書を格納する
  (5) XML Collectionを使うための設計・実装
  (6) XML Collectionでデータマッピングを実現
  (最終回) Webサービス機能を徹底検証する


XML & SOA フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日月間