ヘッダーをスキップ
Oracle XML Developer's Kitプログラマーズ・ガイド
10gリリース3(10.1.3)
B28611-01
  目次
目次
索引
索引

戻る
戻る
次へ
次へ
 

7 XML SQL Utility(XSU)

この章の内容は次のとおりです。

XML SQL Utility(XSU)の概要

XMLはデータ交換の形式になりますが、一方でオブジェクト・リレーショナル・データベースには相当量のデータが存在します。そのため、このオブジェクト・リレーショナルのデータをXMLに変換する機能が必要です。

XML SQL Utility(XSU)を使用すると、次の変換を実行できます。

データベースからのXMLの生成

XSUはSELECT問合せを指定して、データベースへの問合せを実行し、結果をXML文書として戻します。

データベースへのXMLの格納

XSUはXML文書を指定して、その文書からデータを抽出し、データベースの表にそのデータを挿入できます。

XSU機能へのアクセス

次の方法でXML SQL Utilityの機能にアクセスできます。

  • Java APIを使用

  • PL/SQL APIを使用

  • Javaコマンドラインのフロントエンドを使用

XSUの機能

  • DTDを動的に生成します。

  • 生成中、ROW要素のデフォルト・タグ名の変更など、単純な変換を実行します。XSL変換を登録し、生成したXML文書に対して、必要に応じてその変換を適用できます。

  • XML文書を、文書の文字列またはDOM表現で生成します。

  • データベースの表またはビューにXMLを挿入します。XML文書を指定すると、データベース・オブジェクトのレコードを更新または削除できます。

  • ネストされた複雑なXML文書を生成します。フラットな表上にオブジェクト・ビューを作成して、これらのビューを問い合せることで、リレーショナル表にXML文書を格納することもできます。オブジェクト・ビューでは、オブジェクト・リレーショナル・インフラストラクチャを使用して、既存のリレーショナル・データから構造化されたデータを作成できます。

  • SQL問合せを指定してXMLスキーマを生成します。

  • SAX2コールバックのストリームとしてXMLを生成します。

  • 生成中にXML属性をサポートします。特定の列または列のグループをXML要素ではなくXML属性にマップすることを指定する簡単な方法を提供します。

  • SQL識別子からXML識別子へのエスケープが可能です。列名が有効なXMLタグ名ではない場合があります。この問題を回避するには、すべての列名に別名を付けるか、またはタグをエスケープします。

  • オブジェクトまたは表内のXMLType列をサポートします。


    関連資料:

    • XMLTypeが含まれているXSUの使用例については、『Oracle XML DB開発者ガイド』の特にXMLの生成に関する章を参照してください。

    • Java APIの詳細は、『Oracle XML APIリファレンス』を参照してください。

    • 『PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』

    • 第24章「XSU for PL/SQL」


XSUの依存性とインストール

次にXSUに関する重要な情報を示します。


注意:

Oracle9iXMLGenは使用されなくなったため、現在のOracleソフトウェアに付属していません。XMLGENは、XML生成に使用されるDBMS_XMLQueryパッケージ、およびDMLとデータの操作に使用されるDBMS_XMLSaveパッケージに置き換えられています。

移行は簡単です。メソッド名は同じです。現在の新しいXSU for PL/SQLには、より多くのメソッドが含まれています。すべてのメソッドは、第1引数としてコンテキスト・ハンドルを取ります。


XSUの依存性

XML SQL Utility(XSU)は次のコンポーネントに依存します。

  • データベースの接続性 - JDBCドライバ。XSUはすべてのJDBCドライバとともに使用できますが、Oracle JDBCドライバとの使用が最適です。オラクル社では、Oracle以外のデータベースに対して実行しているXSUの保証やサポートは行いません。

  • Oracle XML Parserバージョン2- xmlparserv2.jar。このファイルはOracleインストールに含まれています。xmlparserv2.jarは、Oracle Technology Network(OTN)のWebサイトからダウンロード可能なXDK Javaコンポーネント・アーカイブの一部にもなっています。

  • XSUは、xdb.jarservlet.jarに含まれるクラスにも依存します。これらはOracleインストールにあります。OTNからダウンロード可能なXDK Javaコンポーネント・アーカイブにも含まれています。

XSUのインストール

XSUはOracleソフトウェアのCDに収録されており、OTNで入手可能なXDK Javaコンポーネント・パッケージの一部にもなっています。XSUは次の2つのファイル形式で提供されます。

  • $ORACLE_HOME/lib/xsu12.jar -- XSUを構成するすべてのJavaクラスが含まれます。xsu12.jarの最小要件はJDK1.2およびJDBC2です。

  • $ORACLE_HOME/rdbms/admin/dbmsxsu.sql -- XSU PL/SQL APIを構築するSQLスクリプト。dbmsxsu.sqlを実行する前に、xsu12.jarをデータベースにロードします。

デフォルトでは、Oracleインストーラによって、前述の箇条書き段落で指定したハード・ドライブにXSUがインストールされます。XSUはデータベースにもロードされます。

XSUが最初にOracleをインストールするときにインストールされない場合、後からインストールできます。Oracleインストーラを使用してXSUとその依存コンポーネントをインストールするか、または最新のXDK JavaコンポーネントをOTNからダウンロードできます。

データベースにXSUをロードするには、XSUのインストール方法に応じて、次のいずれかの手順を実行する必要があります。

  • Oracleインストーラによるインストール: ディレクトリをORACLE_HOMEディレクトリに変更してから、rdbms/adminに移動します。initxml.sqlを実行します。

  • OTNからのダウンロードによるインストール: ディレクトリを、ダウンロードおよび展開したXDKツリーのbinディレクトリに変更します。xdk loadスクリプトを実行します。Windowsユーザーはxdkload.batを実行します。

XSUのインストール場所

XSUはJavaで記述されているため、Javaをサポートする任意の層に格納できます。XSUはクライアント・システムにインストールできます。

データベースでのXML SQL Utility

XSUを構成するJavaクラスは、Java対応のOracleデータベースにロードできます。XSUには、XSU Java APIをPL/SQLに公開してPL/SQL APIを作成するPL/SQLラッパーが含まれます。この場合、次の作業を実行できます。

  • データベース内で実行し、XSU Java APIに直接アクセスできる新しいJavaアプリケーションを作成します。

  • PL/SQL APIを介してXSUにアクセスするPL/SQLアプリケーションを作成します。

  • SQLを介して直接XSU機能にアクセスします。

図7-1に、このようなシステムに使用する一般的なアーキテクチャを示します。データベース内で実行するXSUが生成したXMLは、データベースのアドバンスト・キュー内に置いて、他のシステムまたはクライアントにキューさせることができます。XMLは、データベースのストアド・プロシージャ内から使用するか、Webサーバーまたはアプリケーション・サーバーを通じて外部に配信できます。

図7-1では、すべての矢印が両方向です。XSUでは、データを生成および保存できるため、様々なソースからデータベース内で実行しているXSUにデータを配信でき、それを適切なデータベース表に戻すことができます。

図7-1 データベースで実行中のXML SQL Utility

図7-1の説明が続きます
「図7-1 データベースで実行中のXML SQL Utility」の説明

中間層でのXML SQL Utility

アプリケーション・アーキテクチャによっては、データベースから分離した中間層のアプリケーション・サーバーを使用する必要があります。このアプリケーション層には、Oracleデータベース、Oracle Application Server、Javaプログラムをサポートするサード・パーティ製のアプリケーション・サーバーなどがあります。

様々な理由で、SQL問合せまたはResultSetsによって中間層でXMLを生成できます。たとえば、中間層で異なるJDBCデータ・ソースを統合するなどの理由があります。この場合、中間層にXSUをインストールでき、JavaプログラムでJava APIを介してXSUを使用できます。

図7-2に、中間層でXSUを実行するための一般的なアーキテクチャを示します。中間層で、JDBCソースのデータはXSUによってXMLに変換され、Webサーバーまたは他のシステムに送信されます。ここでも全体のプロセスは両方向であるため、XSUを使用してデータをJDBCソース(データベース表またはビュー)に戻すことができます。Oracleデータベース自体をアプリケーション・サーバーとして使用する場合は、JavaのかわりにPL/SQLのフロントエンドも使用できます。

図7-2 中間層で実行中のXML SQL Utility

図7-2の説明が続きます
「図7-2 中間層で実行中のXML SQL Utility」の説明

WebサーバーでのXML SQL Utility

図7-3に示すように、WebサーバーがJavaサーブレットをサポートする場合は、XSUをWebサーバー内で実行できます。この場合、XSUを使用するJavaサーブレットを作成して、そのタスクを実行できます。

XSQLサーブレットはこのタスクのみを行います。XSQLサーブレットは、Oracleが提供する標準のサーブレットです。XSQLサーブレットはXSUの最上位に構築され、XSUの機能にテンプレート形式のインタフェースを提供します。WebサーバーでXML処理を実行するには、サーブレットの複雑なプログラミングを避けるために、XSQLサーブレットを使用できます。


関連項目:

XSQLサーブレットの使用の詳細は、第8章「XSQL Pagesパブリッシング・フレームワーク」を参照してください。

図7-3 Webサーバーで実行中のXML SQL Utility

図7-3の説明が続きます
「図7-3 Webサーバーで実行中のXML SQL Utility」の説明

SQLおよびXML間のマッピングの手引き

この項では、SQLからXML(またはその逆)へのマッピングや変換について説明します。

SQLからXMLへのデフォルトのマッピング

emp1について考えてみます。

CREATE TABLE emp1
(
   empno NUMBER,
   ename VARCHAR2(20),
   job VARCHAR2(20),
   mgr  NUMBER,
   hiredate DATE,
   sal NUMBER,
   deptno NUMBER
);

XSUは、次の問合せを指定してXML文書を生成できます。

select * from emp1:

<?xml version='1.0'?>
<ROWSET>
  <ROW num="1">
    <EMPNO>7369</EMPNO>
    <ENAME>sMITH</ENAME>
    <JOB>clerk</JOB>
    <mgr>7902</mgr>
    <HIREDATE>12/17/1980 0:0:0</HIREDATE>
    <SAL>800</SAL>
    <DEPTNO>20</DEPTNO>
  </ROW>
  <!-- additional rows ... -->
</ROWSET>

生成されたXMLでは、SQL問合せによって戻された行は、<ROWSET>要素を構成するROWSETタグで囲まれています。この要素は、生成されたXML文書のルート要素でもあります。

  • <ROWSET>要素には、1つ以上の<ROW>要素が含まれます。

  • <ROW>要素には、戻されたデータベース表のいずれかの行からのデータが含まれます。特に、各<ROW>要素には、名前とコンテンツが、SQL問合せのSELECTリストで指定されたデータベースの列の名前とコンテンツである要素が1つ以上あります。

  • データベースの列に対応するこれらの要素には、列からのデータが含まれます。

オブジェクト・リレーショナル・スキーマでのSQLからXMLへのマッピング

次に、オブジェクト・リレーショナル・スキーマでのマッピングを示します。AddressTypeオブジェクト・タイプについて考えてみます。これは属性がすべてスカラー型で次のように作成されるオブジェクト・タイプです。

CREATE TYPE AddressType AS OBJECT (
   street VARCHAR2(40),
   city   VARCHAR2(20),
   state  CHAR(2),
   zip    VARCHAR2(10)
);

次に示すEmployeeTypeもオブジェクト型ですが、それ自体がオブジェクト型であるempaddr属性(具体的にはAddressType)を持っています。Employee Typeは次のように作成されます。

CREATE TYPE EmployeeType AS OBJECT
(
  empno NUMBER,
  ename VARCHAR2(20),
  salary NUMBER,
  empaddr AddressType
);

次に示すEmployeeListType型は、その要素がオブジェクト型(EmployeeType)であるコレクション型です。EmployeeListTypeは次のように作成されます。

CREATE TYPE EmployeeListType AS TABLE OF EmployeeType;

最後に示すdept1は、オブジェクト型の列がAddressType、コレクション型の列がEmployeeListTypeになっている表です。

CREATE TABLE dept1
(
  deptno NUMBER,
  deptname VARCHAR2(20),
  deptaddr AddressType,
  emplist  EmployeeListType
)
NESTED TABLE emplist STORE AS emplist_table;

有効な値が表dept1に格納されるとします。問合せselect * from dept1では、XSUによって次のXML文書が生成されます。

<?xml version='1.0'?>
<ROWSET>
   <ROW num="1">
    <DEPTNO>100</DEPTNO>
    <DEPTNAME>Sports</DEPTNAME>
    <DEPTADDR>
      <STREET>100 Redwood Shores Pkwy</STREET>
      <CITY>Redwood Shores</CITY>
      <STATE>CA</STATE>
      <ZIP>94065</ZIP>
    </DEPTADDR>
    <EMPLIST>
      <EMPLIST_ITEM num="1">
         <EMPNO>7369</EMPNO>
         <ENAME>John</ENAME>
         <SALARY>10000</SALARY>
         <EMPADDR>
           <STREET>300 Embarcadero</STREET>
           <CITY>Palo Alto</CITY>
           <STATE>CA</STATE>
           <ZIP>94056</ZIP>
         </EMPADDR>
      </EMPLIST_ITEM>
       <!-- additional employee types within the employee list -->
    </EMPLIST>
  </ROW>
  <!-- additional rows ... -->
</ROWSET>

前述の例と同様に、この例は正規のマッピングを示しています。<ROWSET>には<ROW>要素が含まれ、<ROW>要素には、列に対応した要素が含まれます。すでに述べたように、スカラー型の列に対応する要素には、列からのデータがそのまま含まれます。

複雑な型の列からXMLへのマッピング

複雑な型の列に対応する要素の場合、マッピングはより複雑になります。たとえば、<DEPTADDR>は、オブジェクト型ADDRESSDEPTADDR列に対応しています。したがって、<DEPTADDR>には、ADDRESS型で指定された属性に対応するサブ要素が含まれます。これらのサブ要素は、対応する属性の型が単純か複雑かによって、それ自体がデータやサブ要素を含む場合があります。

XMLへのコレクションのマッピング

データベースのコレクションに対応する要素を処理する場合も、マッピングの方法が異なります。特に、<EMPLIST>要素は、コレクション型EmployeeListTypeEMPLIST列に対応しています。したがって、<EMPLIST>要素は、それぞれがコレクションの要素の1つに対応する<EMPLIST_ITEM>要素のリストを含みます。

前述のマッピングに関するその他の注意点は次のとおりです。

  • <ROW>要素は、カーディナリティ属性numを含みます。

  • 特定の列または属性の値がNULLの場合、その行では、対応するXML要素がすべて省略されます。

  • 最上位のスカラー列の名前がアットマーク(@)で始まる場合、その特定の列はXML要素ではなくXML属性にマップされます。

生成したXMLのカスタマイズ: SQLからXMLへのマッピング

場合によっては、特定の構造を持つXMLを生成する必要があります。生成されたXML文書のデフォルトの構造が要求する構造と異なる場合があるため、このプロセスにはある程度の柔軟性が必要になります。次のいずれかの方法を使用して、生成されたXML文書の構造をカスタマイズできます。

ソースのカスタマイズ

ソースのカスタマイズは、問合せまたはデータベース・スキーマを変更することで行います。最も単純で強力なソースのカスタマイズは次のとおりです。

  • データベース・スキーマで、任意のXML文書構造にマップするオブジェクト・リレーショナル・ビューを作成します。

  • 問合せで次のことを行います。

    • カーソル副問合せまたはキャスト多重集合構造を使用して、フラットなスキーマから取得したXML文書でネストを作成します。

    • 列名および属性名に別名を付けて、任意のXML要素を取得します。

    • アットマーク(@)で始まる識別子を使用して、最上位のスカラー型の列に別名を付け、これらの列をXML要素ではなくXML属性にマップします。たとえばSELECT empno AS "@empno",... FROM empの場合、<ROW>要素が属性EMPNOを持つXML文書が生成されます。

マッピングのカスタマイズ

XML SQL Utilityを使用すると、SQLデータをXMLに変換するために使用するマッピングを変更できます。SQLからXMLへのマッピングでは、次のように変更できます。

  • <ROWSET>タグを変更または省略します。

  • <ROW>タグを変更または省略します。

  • num属性を変更または省略します。これは<ROW>要素のカーディナリティ属性です。

  • 生成されたXML要素名に大/小文字を指定します。

  • コレクションの要素に対応するXML要素が、カーディナリティ属性を持つように指定します。

  • XML文書の日付書式を指定します。

  • XML文書のnull値は、要素を省略せず、NULL属性を使用して表すように指定します。

生成後のカスタマイズ

最後に、前述の方法で必要なカスタマイズが行われない場合、XSUを使用してXSL変換を作成して登録できます。XSUにXSLTを登録して、XSUが生成する任意のXMLにこのXSLTを適用できます。

XMLからSQLへのデフォルトのマッピング

XMLからSQLへのマッピングは、SQLからXMLへのマッピングの逆の操作です。

XMLからSQLへのマッピングとSQLからXMLへのマッピングを比較した場合の次の相違点を考慮してください。

  • XMLからSQLへの変換では、XML属性が無視されます。したがって、XML属性は実際にはSQLにマップされません。

  • SQLからXMLへの変換では、SQL問合せによって作成されたResultSetからXMLに対してマッピングが行われます。この場合、問合せは複数のデータベース表またはビューに対して実行できます。XMLに変換される単一のResultSetが作成されます。XMLからSQLに変換する場合は、次の点に注意してください。

    • 1つのXML文書を複数の表またはビューに挿入するには、ターゲットのスキーマにオブジェクト・リレーショナル・ビューを作成する必要があります。

    • ビューが更新不可能な場合は、INSTEAD-OF-INSERTトリガーを使用できます。

XML文書がターゲットのデータベース・スキーマに完全にマップされない場合は、次の3つの方法で対処できます。

  • ターゲットを変更します。ターゲットのスキーマにオブジェクト・リレーショナル・ビューを作成し、そのビューを新しいターゲットにします。

  • XML文書を変更します。XSLTを使用してXML文書を変換します。XSLTをXSUに登録すると、マッピングを試行する前に、受信したXMLが自動的に変換されます。

  • XSUのXMLからSQLへのマッピングを変更します。XML要素とデータベースの列または属性の一致で大文字と小文字を区別するように、XSUに対して指示できます。

    • ROWのかわりに、データベースの行に対応する要素名を使用するようにXSUに対して指示できます。

    • XML文書の日付を解析するときに使用する日付書式をXSUで指定できます。

XML SQL Utilityの機能

この項では、次のタスクを実行する場合のXSUの機能について説明します。

XSUを使用した選択

XSUによる生成は簡単です。SQL問合せを実行し、データベースからResultSetを取得します。ResultSetに関するメタデータを取得して分析します。「SQLからXMLへのデフォルトのマッピング」で説明したマッピングを使用すると、SQLの結果セットが処理され、XML文書に変換されます。

XSUが処理できない問合せ

XSUでは特定の種類の問合せを処理できません。特に、LONG型またはLONG RAW型の列とSelect句のCURSOR()式が混在している場合、処理できません。LONGおよびLONG RAWは、JDBCがストリームとしてアクセスするデータ型の例で、今は使用されていません。これらの列をCLOBに移行すると、問合せは成功します。

XSUを使用した挿入

特定の表またはビューにXML文書のコンテンツを挿入する場合、XSUは最初にターゲットの表またはビューのメタデータを取得します。XSUはこのメタデータに基づいて、SQL INSERT文を生成します。XML文書からデータを抽出して、適切な列または属性にそのデータをバインドします。最後に文を実行します。

たとえば、ターゲット表がdept1で、dept1からXML文書が生成されるとします。

XSUは、次のようなINSERT文を生成します。

INSERT INTO dept1 (deptno, deptname, deptaddr, emplist) VALUES (?,?,?,?)

次にXSUはXML文書を解析し、レコードごとに、適切な列または属性に適切な値をバインドします。

deptno   <- 100
deptname <- SPORTS
deptaddr <- AddressType('100 Redwood Shores Pkwy','Redwood Shores',
                        'CA','94065')
emplist  <- EmployeeListType(EmployeeType(7369,'John',100000,
            AddressType('300 Embarcadero','Palo Alto','CA','94056'),...)

文を実行します。INSERT処理を最適化して、バッチで挿入およびコミットできます。

XSUを使用した更新

更新および削除は、データベース表内の複数の行に影響するという点で挿入と異なります。挿入では、表にトリガーまたは制約がない場合は、XML文書の1つのROW要素の影響を受けるのは表内で最大1つの行のみです。

ただし、更新および削除では、一致する列が表内のキー列でない場合は、XML要素が複数の行と一致する場合があります。更新では、更新する行を識別するためにXSUが必要とするキー列のリストを用意する必要があります。たとえば、DEPTNAMESportsではなくSportsDeptに更新する場合のXML文書は次のようになります。

<ROWSET>
  <ROW num="1">
    <DEPTNO>100</DEPTNO>
    <DEPTNAME>SportsDept</DEPTNAME>
  </ROW>
</ROWSET>

キー列としてDEPTNOを指定します。次のUPDATE文が生成されます。

UPDATE dept1 SET deptname = ? WHERE deptno = ?

値を次のようにバインドします。

deptno <- 100
deptname <- SportsDept

更新の場合は、XML文書にあるすべての要素を更新するのではなく、列の集合のみを更新するように選択できます。

XSUを使用した削除

削除の場合は、削除の対象として行を識別するように、キー列の集合の指定を選択できます。キー列の集合を指定しないと、DELETE文は文書に指定されたすべての列を一致させようとします。次のようなXML文書があるとします。

<ROWSET>
 <ROW num="1">
  <DEPTNO>100</DEPTNO>
  <DEPTNAME>Sports</DEPTNAME>
  <DEPTADDR>
      <STREET>100 Redwood Shores Pkwy</STREET>
      <CITY>Redwood Shores</CITY>
      <STATE>CA</STATE>
      <ZIP>94065</ZIP>
  </DEPTADDR>
 </ROW>
 <!-- additional rows ... -->
</ROWSET>

削除するために、XSUはDELETE文(ROW要素ごとに1つ)を構築します。

DELETE FROM dept1 WHERE deptno = ? AND deptname = ? AND deptaddr = ?

バインドは次のとおりです。

deptno   <- 100
deptname <- sports
deptaddr <- addresstype('100 redwood shores pkwy','redwood city','ca',
            '94065')

XSUコマンドラインのフロントエンドOracleXMLの使用

XSUには、XMLをすぐに生成および挿入できる簡単なコマンドライン・フロントエンドが付属しています。

XSUのコマンドライン・オプションは、JavaクラスOracleXMLを介して利用できます。次のようにコールしてこのクラスを起動します。

java OracleXML

これにより、フロントエンド使用情報が出力されます。XSUのコマンドライン・フロントエンドを実行するには、最初に実行ファイルが置かれている場所を指定します。CLASSPATHに次のライブラリを追加します。

また、XSUはOracle XML ParserおよびJDBCドライバに依存するため、これらのコンポーネントの場所を認識させます。これを実行するには、CLASSPATHに次のライブラリの場所を含める必要があります。

XSUのコマンドラインを使用したXMLの生成

XSUの生成機能では、XSUのgetXMLパラメータを使用します。たとえば、hrスキーマにあるemployees表に問合せを行ってXML文書を生成するには、次の構文を使用します。

java OracleXML getXML -user "hr/hr" "select * from employees"

これにより、次のタスクが実行されます。

  1. 現在のデフォルト・データベースへの接続

  2. 問合せselect * from employeesの実行

  3. 結果のXMLへの変換

  4. 結果の表示

getXMLパラメータは様々なオプションをサポートします。これらのオプションについては、次のセクションで説明します。

XSUのOracleXML getXMLオプション

表7-1に、OracleXML getXMLオプションを示します。

表7-1 XSUのOracleXML getXMLオプション

getXMLオプション 説明

-user "username/password"

データベースに接続するためのユーザー名およびパスワードを指定します。このオプションを指定しないと、デフォルトでscott/tigerが指定されます。接続文字列も指定されている点に注意してください。ユーザー名およびパスワードを接続文字列の一部として指定できます。

-conn JDBC_connect_string

JDBCデータベースの接続文字列を指定します。デフォルトの接続文字列は"jdbc:oracle:oci:@"です。

-withDTD

XML文書とともにDTDも生成するようにXSUに指示します。

-withSchema

XML文書とともにスキーマも生成するようにXSUに指示します。

-rowsetTag tag_name

rowsetタグ(問合せによって戻されたレコードに対応するすべてのXML要素を囲むタグ)を指定します。デフォルトのrowsetタグは、ROWSETです。rowsetに空の文字列を指定すると、XSUではrowset要素を完全に省略します。

-rowTag tag_name

rowタグ(データベース行に対応するデータを囲むタグ)を指定します。デフォルトのROWタグはROWです。ROWタグに空の文字列を指定すると、XSUではROWタグを完全に省略します。

-rowIdAttr row_id_attribute_name

ROW要素の属性に名前を付け、rowsの数を追跡します。デフォルトでは、この属性はnumといいます。rowID属性に空の文字列("")を指定すると、XSUは属性を省略します。

-rowIdColumn row_Id_column_name

問合せからのスカラー列の1つの値が、rowID属性の値として使用されるように指定します。

-collectionIdAttr collection_id_attribute name

XMLリスト要素の属性に名前を付け、リストの要素の数を追跡します(生成されるXMLリストは、カーソル問合せまたはコレクションのいずれかに対応します)。rowID属性に空の文字列("")を指定すると、XSUは属性を省略します。

-useNullAttrId

属性NULL (TRUE/FALSE)を使用して、要素がnullであるかどうかを示します。

-styleSheet stylesheet_URI

XML PI(処理命令)にスタイルシートを指定します。

-stylesheetType stylesheet_type

XML PI(処理命令)にスタイルシートの型を指定します。

-errorTag error tag_name

エラー・タグ(XMLにフォーマットされたエラー・メッセージを囲むタグ)を指定します。

-raiseNoRowsException

行が戻されなかった場合に例外を発生させるようにXSUに命令します。

-maxRows maximum_rows

XMLに変換するために取得される行の最大数を指定します。

-skipRows number_of_rows_to_skip

スキップされる行の数を指定します。

-encoding encoding_name

生成されるXMLのキャラクタ・セットのエンコーディングを指定します。

-dateFormat date_format

XML文書内の日付値用の書式を指定します。

-fileName SQL_query_fileName

| sql_query

問合せを含むファイル名または問合せ自体を指定します。

-useTypeForCollElemTag

列と要素タグの型名を使用します(デフォルトではXSUはcolumn-name_itemを使用)。

-setXSLTRef URI

XSLT外部実体参照を設定します。

-useLowerCase

| - useUpperCase

小文字または大文字のタグ名をそれぞれ生成します。デフォルトでは、大/小文字は、タグ名の生成元のSQLオブジェクト名に一致します。

-withEscaping

SQLオブジェクト名では有効であっても、XMLタグでは無効な文字があります。このオプションは、このような文字を検出した場合、例外を発生させるのではなくエスケープすることを意味します。

-raiseException

デフォルトでは、XSUがエラーを捕捉し、XMLエラーを発行します。これにより、発生したJava例外をXSUが実際にスローするように動作が変更されます。


XSUのコマンドライン(putXML)を使用したXMLの挿入

hrスキーマのemployees表にXML文書を挿入するには、次の構文を使用します。

java OracleXML putXML -user "hr/hr" -fileName "/tmp/temp.xml" "employees"

これにより、次のタスクが実行されます。

  1. 現在のデータベースに接続

  2. 指定のファイルからのXML文書の読取り

  3. タグと列名を一致させてXML文書を解析

  4. employees表への値の適切な挿入


    注意:

    XSUのコマンドライン・フロントエンドputXMLは、現在XSUの挿入機能のみをパブリッシュします。

XSUのOracleXML putXMLオプション

表7-2に、putXMLオプションを示します。

表7-2 XSUのOracleXML putXMLオプション

putXMLオプション 説明

-user "username/password"

データベースに接続するためのユーザー名およびパスワードを指定します。このオプションを指定しないと、デフォルトでscott/tigerが指定されます。接続文字列も指定します。ユーザー名およびパスワードはこの接続文字列の一部として指定できます。

-conn JDBC_connect_string

JDBCデータベースの接続文字列を指定します。デフォルトの接続文字列は"jdbc:oracle:oci:@"です。

-batchSize batching_size

バッチ・サイズを指定します。これによって、バッチされ、一度にデータベースに挿入される行の数を制御し、パフォーマンスを改善できます。

-commitBatch commit_size

コミットが実行される挿入レコードの数を指定します。自動コミットをTRUE(デフォルト)にしている場合は、commitBatchを設定しても処理は行われないことに注意してください。

-rowTag tag_name

rowタグ(データベース行に対応するデータを囲むタグ)を指定します。デフォルトのROWタグはROWです。rowタグに空の文字列を指定すると、XML文書で行を囲むタグが使用されないことをXSUに命令します。

-dateFormat date_format

XML文書内の日付値用の書式を指定します。

-ignoreCase

列名とタグ名を大/小文字を区別せずに一致させます(たとえば、ignoreCaseがオンになっている場合、EmpNoEMPNOは一致します)。

-fileName file_name

挿入するXML文書(ローカル・ファイル)を指定します。

-URL URL

文書をフェッチするURLを指定します。

-xmlDoc xml_document

コマンドライン上の文字列としてXML文書を指定します。

-tableName table

値を挿入する表の名前です。

-withEscaping

文書の生成時にSQLからXMLへの名前のエスケープを使用すると、逆マッピングが有効になります。

-setXSLT URI

挿入前にXML文書に適用するXSLTです。

-setXSLTRef URI

XSLT外部実体参照を設定します。


XSUのJava API

XML SQL Utility Java APIは、次の2つのクラスによって構成されています。

XSUのOracleXMLQueryを使用したXMLの生成

OracleXMLQueryクラスは、XSUのJava APIのXML生成部分を構成します。図7-4に、OracleXMLQueryを使用してXMLを生成する場合に必要な基本手順を示します。

  1. 接続を作成します。

  2. SQL文字列またはResultSetオブジェクトを指定することにより、OracleXMLQueryインスタンスを作成します。

  3. 結果をDOMツリーまたはXML文字列として取得します。

図7-4 XML SQL Utility for Javaを使用したXMLの生成: 基本手順

図7-4の説明が続きます
「図7-4 XML SQL Utility for Javaを使用したXMLの生成: 基本手順」の説明

XSUを使用したSQL問合せからのXMLの生成

次の例では、SQL問合せを指定して、XSUがDOM表現または文字列表現でXML文書を生成する方法を示します。図7-5を参照してください。

図7-5 XML SQL Utilityを使用したXMLの生成

図7-5の説明が続きます
「図7-5 XML SQL Utilityを使用したXMLの生成」の説明

XMLを生成するXSUの例1: 表のemployeesからの文字列の生成(Java)

1. 接続の作成

  • XMLを生成する前に、データベースへの接続を作成する必要があります。JDBC接続文字列を指定して接続を取得できます。最初にOracle JDBCクラスを登録してから、次のように接続を作成します。

    // import the Oracle driver..
    import oracle.jdbc.*;
    
    // Load the Oracle JDBC driver
    DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
    
    // Create the connection.
    Connection conn =
       DriverManager.getConnection("jdbc:oracle:oci:@","hr","hr");
    
    

    ここでは、JDBC OCIドライバのデフォルト接続を使用しています。パスワードtigerを指定するscottスキーマに接続できます。

    JDBCシン・ドライバを使用して、データベースに接続することもできます。シン・ドライバはPure Javaで作成されており、アプレットまたは他のすべてのJavaプログラムからコールできます。


    関連資料:

    詳細は、『Oracle Database Java開発者ガイド』を参照してください。




  • 次に、JDBCシン・ドライバを使用して接続する例を示します。

    // Create the connection.
    Connection conn =
       DriverManager.getConnection("jdbc:oracle:thin:@dlsun489:1521:ORCL",
       "hr","hr");
    
    

    シン・ドライバでは、ホスト名(dlsun489)、ポート番号(1521)、およびマシン上で特定のOracleインスタンスを識別するOracle SID(ORCL)を指定する必要があります。

  • サーバーで実行する場合、接続は必要ありません。サーバー側のJavaコードを記述する場合(サーバーで実行するコードを記述する場合)、サーバー側の内部ドライバがデフォルト・セッション内で実行されるため、ユーザー名とパスワードを使用して接続を確立する必要はなく、すでに接続されています。この場合、oracle.jdbc.driver.OracleDriver()クラスでdefaultConnection()をコールして、次のように現在の接続を取得します。

    import oracle.jdbc.*;
    // Load the Oracle JDBC driver
    DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
    Connection conn =  new oracle.jdbc.OracleDriver().defaultConnection ();
    
    

    これ以降は、クライアントからのOCI接続を使用しているか、またはすでに接続オブジェクトが作成されていると仮定して説明します。必要に応じて、適切な接続作成を使用します。


注意:

oracle.xml.sql.dataset.OracleXMLDataSetExtJdbcはOracle JDBCにのみ使用し、oracle.xml.sql.dataset.OracleXMLDataSetGenJdbcはOracle以外のJDBCに使用します。

2. OracleXMLQueryクラス・インスタンスの作成

接続を登録したら、次のように実行するSQL問合せを指定してOracleXMLQueryクラス・インスタンスを作成します。

// import the query class in to your class
import oracle.xml.sql.query.OracleXMLQuery;

OracleXMLQuery qry = new OracleXMLQuery (conn, "select * from employees");

これで問合せクラスを使用する準備ができました。

3. DOMツリーまたはXML文字列としての結果の取得:

  • DOMオブジェクトの出力。文字列ではなく、DOMオブジェクトが必要な場合、次のようにDOM出力をリクエストできます。

    org.w3c.DOM.Document domDoc = qry.getXMLDOM();
    
    

    さらにDOM検索を使用します。

  • XMLの文字列出力。結果のXML文字列を取得できます。

    String xmlString = qry.getXMLString();
    
    

次に、XML文字列を抽出(生成)するプログラムの詳細を示します。このプログラムは文字列を取得し、標準出力に出力します。

import oracle.jdbc.*;
import oracle.xml.sql.query.OracleXMLQuery;
import java.lang.*;
import java.sql.*;

// class to test the String generation!
class testXMLSQL {

   public static void main(String[] argv)
   {

     try{
      // create the connection
      Connection conn  = getConnection("hr","hr");

      // Create the query class.
      OracleXMLQuery qry = new OracleXMLQuery(conn, "select * from employees");

      // Get the XML string
      String str = qry.getXMLString();

      // Print the XML output
      System.out.println(" The XML output is:\n"+str);
      // Always close the query to get rid of any resources..
     qry.close();
     }catch(SQLException e){
      System.out.println(e.toString());
     }
   }

   // Get the connection given the user name and password..!
   private static Connection getConnection(String username, String password)
       throws SQLException
   {
      // register the JDBC driver..
       DriverManager.registerDriver(new oracle.jdbc.OracleDriver());


      // Create the connection using the OCI driver
       Connection conn =
            DriverManager.getConnection("jdbc:oracle:oci:@",username,password);

      return conn;
   }
}

このプログラムの実行方法

このプログラムを実行するには、次の手順を実行します。

  1. testXMLSQL.javaというファイルにコードを格納します。

  2. Javaコンパイラjavacを使用してプログラムをコンパイルします。

  3. java testXMLSQLを指定してプログラムを実行します。

Java実行可能ファイルがクラスを検索できるように、CLASSPATHがこのディレクトリを指すようにする必要があります。このプログラムのコンパイルおよび実行には、OracleのJDeveloperなどのビジュアルなJavaツールを各種使用できます。このプログラムを実行すると、画面にXMLファイルが出力されます。

XMLを生成するXSUの例2: 表のemployeesからのDOMの生成(Java)

DOMは、解析したツリー状のフォームでXML文書を表します。各XMLエンティティがDOMノードになります。したがって、XMLの要素と属性がDOMノードになり、その子が子ノードになります。XSUが生成したXMLからDOMツリーを生成するには、XSUにDOM文書を直接リクエストできます。この方法は、XML文書の文字列表現を作成するオーバーヘッドを伴わずに保存し、XML文書を解析してDOMツリーを生成します。

XSUは、パーサーをコールしてデータ値からDOMツリーを直接構築します。次の例では、DOMツリーの生成方法を示します。この例ではDOMツリー内を移動し、すべてのノードを1つずつ出力します。

import org.w3c.dom.*;
import oracle.xml.parser.v2.*;
import java.sql.*;
import oracle.xml.sql.query.OracleXMLQuery;
import java.io.*;

 class domTest{

   public static void main(String[] argv)
   {
      try{
      // create the connection
      Connection conn  = getConnection("hr","hr");

      // Create the query class.
   OracleXMLQuery qry = new OracleXMLQuery(conn, "select * from employees");

      // Get the XML DOM object. The actual type is the Oracle Parser's DOM
      // representation. (XMLDocument)
      XMLDocument domDoc = (XMLDocument)qry.getXMLDOM();

      // Print the XML output directly from the DOM
      domDoc.print(System.out);

      // If you instead want to print it to a string buffer you can do this.
      StringWriter s = new StringWriter(10000);
      domDoc.print(new PrintWriter(s));
      System.out.println(" The string version ---> "+s.toString());

      qry.close();   // Allways close the query!!
      }catch(Exception e){
        System.out.println(e.toString());
      }
    }

    // Get the connection given the user name and password..!
    private static Connection getConnection(String user, String passwd)
      throws SQLException
    {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn =
          DriverManager.getConnection("jdbc:oracle:oci:@",user,passwd);
     return conn;
   }
}

結果ページの区切り: skipRowsおよびmaxRows

これまでに示した例では、XML SQL Utility(XSU)はResultSetまたは問合せを取得して、問合せのすべての行から文書全体を生成しました。一度に100行を取得するには、最初の100行、次の100行などを取得する際に異なる問合せを発行する必要があります。また、問合せの最初の5行をスキップして結果を生成することはできません。

これらの結果を取得するには、XSUのskipRowsパラメータおよびmaxRowsパラメータの設定を使用します。

たとえば、skipRowsの値を5に設定し、maxRowsの値を10に設定すると、XSUは最初の5行をスキップしてから次の10行のXMLを生成します。

ユーザーのセッション期間にわたるオブジェクトのオープン状態の保持

Webのシナリオによっては、問合せオブジェクトをユーザーのセッション中オープンにしておくことが必要な場合があります。たとえば、ページ区切り形式でユーザーの検索結果を提供するWeb検索エンジンの場合について考えてみます。最初のページに10個の結果、次のページに次の10個のように結果が表示されます。

これを実行するには、一度に10行ずつ変換し、ResultSetをアクティブ状態にするようXSUにリクエストします。こうするとXSUに対して次に追加の結果を要求したときに、前回の生成が終了した箇所から生成を開始します。

行数または行内の列数が多すぎる場合

行数または行内の列数が多すぎる場合もあります。この場合は、それぞれのサイズが小さい複数の文書を生成できます。maxRowsパラメータやkeepObjectOpen関数を使用して、これらのケースも処理できます。

keepObjectOpenファンクション

通常、指定したSQL問合せ文字列で結果セットを作成した場合、すべての結果が生成されるとすぐに、OracleXMLQueryResultSetを内部的にクローズします。OracleXMLQueryがこれ以上の結果を必要としないと想定するためです。ただし、前述のケースのように、その状態を維持するには、keepObjectOpenファンクションをコールしてカーソルをアクティブにする必要があります。次の例を参照してください。

XMLを生成するXSUの例3: 結果ページの区切り:(Java)

この例では、XSU for Java APIを使用してXMLページを生成できる方法を示しています。

import oracle.sql.*;
import oracle.jdbc.*;

import oracle.xml.sql.*;
import oracle.xml.sql.query.*;
import oracle.xml.sql.dataset.*;
import oracle.xml.sql.docgen.*;

import java.sql.*;
import java.io.*;

public class b
{
  public static void main(String[] args) throws Exception
  {

    DriverManager.registerDriver(new oracle.jdbc.OracleDriver());

    Connection conn =
      DriverManager.getConnection"jdbc:oracle:oci:@", "hr", "hr"();

    Statement stmt =
conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                                          ResultSet.CONCUR_READ_ONLY);

    String sCmd = "SELECT FIRST_NAME, LAST_NAME FROM HR.EMPLOYEES";
    ResultSet rs = stmt.executeQuery(sCmd);

    OracleXMLQuery xmlQry = new OracleXMLQuery(conn, rs);
    xmlQry.keepObjectOpen(true);
    //xmlQry.setRowIdAttrName("");
    xmlQry.setRowsetTag("ROWSET");
    xmlQry.setRowTag("ROW");
    xmlQry.setMaxRows(20);

    //rs.beforeFirst();
    String sXML = xmlQry.getXMLString();
    System.out.println(sXML);
  }
}

ResultSetオブジェクトからのXMLの生成

SQL問合せを指定して、その結果をXMLとして取得できることはわかりました。前述の例では、ページで区切られた結果を取得しました。ただしWebの場合、結果の次のページのみではなく前のページを取得する必要がある場合もあります。このスクロール機能を可能にするには、スクロール可能なResultSetを使用できます。このResultSetオブジェクトを使用して結果セット内を移動し、移動するたびにXSUを使用してXMLを生成します。次の例では、この実行方法を示します。

XMLを生成するXSUの例4: JDBC ResultSetsからのXMLの生成(Java)

この例では、JDBC ResultSetを使用してXMLを生成する方法を示します。ResultSetは、バッチ・サイズの設定や値のバインドなど、XSUで直接処理されない場合に使用する必要があることに注意してください。この例では、以前定義したpageTestクラスを拡張して任意のページを処理します。

public class pageTest
{
   Connection conn;
   OracleXMLQuery qry;
    Statement stmt;
   ResultSet rset;
   int lastRow = 0;

   public pageTest(String sqlQuery)
   {
       try{
           conn  = getConnection("hr","hr");
           stmt = conn.createStatement();// create a scrollable Rset
           ResultSet rset = stmt.executeQuery(sqlQuery); // get the result set.
           qry = new OracleXMLQuery(conn,rset); // create an OracleXMLQuery
                                                // instance
           qry.keepCursorState(true); // Don't lose state after the first fetch
           qry.setRaiseNoRowsException(true);
           qry.setRaiseException(true);
       }
     catch (Exception e )
     {
         e.printStackTrace(System.out);
     }
   }

    // Get the connection given the user name and password..!
    private static Connection getConnection(String user, String passwd)
      throws SQLException
    {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn =
          DriverManager.getConnection("jdbc:oracle:oci:@",user,passwd);
     return conn;
   }

   // Returns the next XML page..!
   public String getResult(int startRow, int endRow)
   {
     qry.setMaxRows(endRow-startRow); // set the max # of rows to retrieve..!
     return qry.getXMLString();
   }

   // Function to still perform the next page.
   public String nextPage()
   {
     String result = getResult(lastRow,lastRow+10);
     lastRow+= 10;
     return result;
   }

   public void close() throws SQLException
   {
     stmt.close();   // close the statement..
     conn.close();   // close the connection
     qry.close();    // close the query..
   }

   public static void main(String[] argv)
   {
     String str;
     try{
         pageTest test = new pageTest("select * from employees");

         int i = 0;
         // Get the data one page at a time..!!!!!
         while ((str = test.getResult(i,i+10))!= null)
             {
                 System.out.println(str);
                 i+= 10;
             }
         test.close();
     }
     catch (Exception e )
     {
         e.printStackTrace(System.out);
     }
   }
}

XMLを生成するXSUの例5: プロシージャ戻り値からのXMLの生成

OracleXMLQueryクラスは、問合せ文字列またはResultSetに対してのみXML変換を行います。しかし、PL/SQLプロシージャを使用し、このプロシージャがREFカーソルを戻す場合のアプリケーションでは、変換はどのように行われるのでしょうか。

この場合、前述のResultSet変換メカニズムを使用してタスクを実行できます。REFカーソルはPL/SQL内のカーソル・オブジェクトへの参照です。これらのカーソル・オブジェクトは、一連の値を取得するために繰り返し処理できる有効なSQL文です。これらのREFカーソルは、JavaではOracleResultSetオブジェクトに変換されます。

これらのプロシージャを実行し、OracleResultSetオブジェクトを取得したら、それをOracleXMLQueryオブジェクトに送信して必要なXMLを取得できます。

REFカーソルを定義してそれを戻す次のPL/SQLファンクションを考えてみます。

CREATE OR REPLACE PACKAGE BODY testRef IS

  function testRefCur RETURN empREF is
  a empREF;
  begin
      OPEN a FOR select * from hr.employees;
      return a;
  end;
end;
/

このファンクションをコールするたびに、select * from employees問合せに対してカーソル・オブジェクトをオープンし、そのカーソル・インスタンスを戻します。オブジェクトをXMLに変換するには、次のようにします。

import org.w3c.dom.*;
import oracle.xml.parser.v2.*;
import java.sql.*;
import oracle.jdbc.*;
import oracle.xml.sql.query.OracleXMLQuery;
import java.io.*;
public class REFCURtest
{
   public static void main(String[] argv)
     throws SQLException
   {
      String str;
      Connection conn  = getConnection("hr","hr"); // create connection

      // Create a ResultSet object by calling the PL/SQL function
      CallableStatement stmt =
         conn.prepareCall("begin ? := testRef.testRefCur(); end;");

      stmt.registerOutParameter(1,OracleTypes.CURSOR); // set the define type

      stmt.execute();   // Execute the statement.
      ResultSet rset = (ResultSet)stmt.getObject(1);  // Get the ResultSet

      OracleXMLQuery qry = new OracleXMLQuery(conn,rset); // prepare Query class
      qry.setRaiseNoRowsException(true);
      qry.setRaiseException(true);
      qry.keepCursorState(true);        // set options (keep the cursor active.
      while ((str = qry.getXMLString())!= null)
           System.out.println(str);

      qry.close();    // close the query..!

      // Note since we supplied the statement and resultset, closing the
      // OracleXMLquery instance will not close these. We need to
      // explicitly close this ourselves..!
      stmt.close();
      conn.close();
   }
    // Get the connection given the user name and password..!
    private static Connection getConnection(String user, String passwd)
      throws SQLException
    {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn =
          DriverManager.getConnection("jdbc:oracle:oci:@",user,passwd);
     return conn;
   }

}

一方でスタイルシートを適用するには、applyStylesheet()コマンドを使用します。このコマンドを使用すると、出力を生成する前にスタイルシートを強制的に適用します。

NoRowsExceptionの発生

XSUは、処理する行がない場合はNULL文字列のみを戻します。ただし、アプリケーションが例外ハンドラを使用して例外を処理できるように、行がなくなるたびに例外を発生させることが望ましい状態です。setRaiseNoRowsException()を設定すると、出力用に生成する行がなくなるたびに、XSUはoracle.xml.sql.OracleXMLSQLNoRowsExceptionを発生させます。これはランタイムの例外であり、不要であれば捕捉する必要はありません。

XMLを生成するXSUの例6: 行がない場合の例外(Java)

次のコードは、前述の例を拡張したもので、NULL文字列の確認ではなく、例外を使用しています。

public class pageTest {
    .... // rest of the class definitions....

   public static void main(String[] argv)
   {
     pageTest test = new pageTest("select * from employees");

     test.qry.setRaiseNoRowsException(true); // ask it to generate exceptions
     try
     {
        while(true)
         System.out.println(test.nextPage());
     }
     catch(oracle.xml.sql.OracleXMLSQLNoRowsException e)
     {
       System.out.println(" END OF OUTPUT ");
       try{
           test.close();
       }
       catch ( Exception ae )
       {
           ae.printStackTrace(System.out);
       }
     }
   }
}


注意:

終了を確認する条件が、結果がNULLかどうかの確認から、例外ハンドラに変更されたことに注意してください。

XSU OracleXMLSaveを使用したデータベースへのXMLの格納

これまでに問合せをXMLに変換する方法を見てきました。ここではXSUを使用して、表またはビューにXMLを戻す方法を示します。oracle.xml.sql.dml.OracleXMLSaveクラスがこの機能を提供します。このクラスにはXMLを表に挿入して、既存の表をXML文書で更新し、XML要素値に基づいて表から行を削除するメソッドがあります。

どのような場合でも、指定したXML文書が解析され、要素を確認してターゲット表またはビューの列名にタグ名を一致させるようにします。要素はSQL型に変換され、適切な文にバインドされます。図7-6に、XSUを使用してXMLを格納するプロセスを示します。

図7-6 XSUを使用したデータベースへのXMLの格納

図7-6の説明が続きます
「図7-6 XSUを使用したデータベースへのXMLの格納」の説明

ROW要素のリストを含むXML文書について見てみます。それぞれのROW要素が個別のDML操作(表またはビューに対するINSERTUPDATEまたはDELETE)を構成します。

XSUを使用した挿入処理(Java API)

表またはビューに文書を挿入するには、表名またはビュー名と文書を指定します。XSUは文書(文字列が指定されている場合)を解析し、INSERT文を作成してこの文にすべての値をバインドします。デフォルトでは、XSUは値を表またはビューのすべての列に値を挿入します。存在しない要素はNULL値として処理されます。次の例では、employees表から生成したXML文書を比較的簡単に表に格納する方法を示します。

XMLを挿入するXSUの例7: すべての列へのXML値の挿入(Java)

この例では、すべての列にXML値を挿入します。

// This program takes as an argument the file name, or a url to
// a properly formated XML document and inserts it into the HR.EMPLOYEES table.
import java.sql.*;
import oracle.xml.sql.dml.OracleXMLSave;
public class testInsert
{
   public static void main(String argv[])
     throws SQLException
  {
     DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
     Connection conn =
          DriverManager.getConnection("jdbc:oracle:oci:@","hr","hr");

     OracleXMLSave sav = new OracleXMLSave(conn, "employees");
     sav.insertXML(sav.getURL(argv[0]));
     sav.close();
   }
}

次の形式のINSERT文が生成され、

INSERT INTO hr.employees (employee_id, last_name, job_id, manager_id,
            hire_date, salary, department_id) VALUES(?,?,?,?,?,?,?);

列名と一致している入力XML文書内の要素タグが照合され、その値がバインドされます。

次のXML文書をファイルに格納し、

<?xml version='1.0'?>
<ROWSET>
 <ROW num="1">
    <EMPLOYEE_ID>7369</EMPLOYEE_ID>
    <LAST_NAME>Smith</LAST_NAME>
    <JOB_ID>CLERK</JOB_ID>
    <MANAGER_ID>7902</MANAGER_ID>
    <HIRE_DATE>12/17/1980 0:0:0</HIRE_DATE>
    <SALARY>800</SALARY>
    <DEPARTMENT_ID>20</DEPARTMENT_ID>
 </ROW>
  <!-- additional rows ... -->
</ROWSET>

そのファイルを前述のプログラムに指定すると、指定した値に対し、7369, Smith, CLERK, 7902, 12/17/1980,800,20の値を含むemployees表に新しい行が生成されます。行要素内に存在しない要素は、NULL値として扱われます。

XMLを挿入するXSUの例8: 列へのXML値の挿入(Java)

すべての列に値を挿入する必要がない場合もあります。取得する値のグループが完全なセットではなく、残りの列にトリガーまたはデフォルト値を使用する必要がある場合が当てはまります。次のコードに、この実行方法を示します。

従業員番号、名前、仕事の値のみを取得して、給与、管理者、部署番号、入社日の各フィールドには自動的に値が入力されると想定します。最初にINSERT文を実行する列名のリストを作成して、そのリストをOracleXMLSaveインスタンスに渡します。

import java.sql.*;
import oracle.xml.sql.dml.OracleXMLSave;
public class testInsert
{
   public static void main(String argv[])
     throws SQLException
   {
      Connection conn = getConnection("hr","hr");
      OracleXMLSave sav = new OracleXMLSave(conn, "hr.employees");

      String [] colNames = new String[3];
      colNames[0] = "EMPLOYEE_ID";
      colNames[1] = "LAST_NAME";
      colNames[2] = "JOB_ID";

      sav.setUpdateColumnList(colNames); // set the columns to update..!

      // Assume that the user passes in this document as the first argument!
      sav.insertXML(sav.getURL(argv[0]));
      sav.close();
   }
   // Get the connection given the user name and password..!
    private static Connection getConnection(String user, String passwd)
      throws SQLException
    {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn =
          DriverManager.getConnection("jdbc:oracle:oci:@",user,passwd);
     return conn;
   }
}

INSERT文が生成されます。

INSERT INTO hr.employees (employee_id, last_name, job_id) VALUES (?, ?, ?);

前述の例では、挿入した文書に他の列の値(HIRE_DATEなど)が含まれていても、それらの値は無視されます。また、挿入操作は、入力に存在する各ROW要素に対して実行されます。これらの挿入はデフォルトでバッチされます。

XSUを使用した更新処理(Java API)

XML文書から表への値の挿入方法を理解したところで、特定の値のみを更新する方法を見ていきます。XML文書では、従業員の給与と配属部署を更新する場合、次のようになります。

<ROWSET>
 <ROW num="1">
   <EMPLOYEE_ID>7369</EMPLOYEE_ID>
   <SALARY>1800</SALARY>
   <DEPARTMENT_ID>30</DEPARTMENT_ID>
 </ROW>
 <ROW>
    <EMPLOYEE_ID>2290</EMPLOYEE_ID>
    <SALARY>2000</SALARY>
    <HIRE_DATE>12/31/1992</HIRE_DATE>
  <!-- additional rows ... -->
</ROWSET>

XSUを使用して値を更新できます。更新の場合は、キー列名のリストでXSUを指定する必要があります。これらの列は、UPDATE文のWHERE句で構成されます。以前に示したemployees表では、従業員番号(employee_id)列がキーを構成します。このキーを使用して、更新を行います。

XMLを更新するXSUの例9: keyColumnsを使用した表の更新(Java)

この例では、keyColumnsを使用してtableおよびempを更新します。

import java.sql.*;
import oracle.xml.sql.dml.OracleXMLSave;
public class testUpdate
{
   public static void main(String argv[])
     throws SQLException
   {
      Connection conn = getConnection("hr","hr");
      OracleXMLSave sav = new OracleXMLSave(conn, "hr.employees");

      String [] keyColNames = new String[1];
      keyColNames[0] = "EMPLOYEE_ID";
      sav.setKeyColumnList(keyColNames);

      // Assume that the user passes in this document as the first argument!
      sav.updateXML(sav.getURL(argv[0]));
      sav.close();
   }
   // Get the connection given the user name and password..!
    private static Connection getConnection(String user, String passwd)
      throws SQLException
    {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn =
          DriverManager.getConnection("jdbc:oracle:oci:@",user,passwd);
     return conn;
   }
}

この例では、2つのUPDATE文が生成されます。最初のROW要素には、UPDATE文が生成され、SALARYフィールドとHIRE_DATEフィールドが次のように更新されます。

UPDATE hr.employees SET salary = 2000 AND hire_date = 12/31/1992 WHERE employee_id = 2290;

2番目のrow要素の場合、次の文が生成されます。

UPDATE hr.employees SET salary = 2000 AND hire_date = 12/31/1992 WHERE employee_id = 2290;

XMLを更新するXSUの例10: 指定した列のリストの更新(Java)

更新する列のリストを指定できます。すべてのROW要素に同じUPDATE文を使用できるため、列リストを指定すると処理速度が向上します。また、XML文書内にある他のタグを無視できます。


注意:

更新する列のリストを指定すると、更新する列に対応する要素が存在しない場合は、その要素がNULLとして処理されます。

更新するすべての要素がXML文書内のすべてのROW要素と同じであることわかっていれば、setUpdateColumnNames()ファンクションを使用して、更新する列のリストを設定できます。

import java.sql.*;
import oracle.xml.sql.dml.OracleXMLSave;
public class testUpdate
{
   public static void main(String argv[])
     throws SQLException
   {
      Connection conn = getConnection("hr","hr");
      OracleXMLSave sav = new OracleXMLSave(conn, "hr.employees");

      String [] keyColNames = new String[1];
      keyColNames[0] = "EMPLOYEE_ID";
      sav.setKeyColumnList(keyColNames);

      // you create the list of columns to update..!
      // Note that if you do not supply this, then for each ROW element in the
      // XML document, you would generate a new update statement to update all
      // the tag values (other than the key columns)present in that element.
      String[] updateColNames = new String[2];
      updateColNames[0] = "SALARY";
      updateColNames[1] = "JOB_ID";
      sav.setUpdateColumnList(updateColNames); // set the columns to update..!

      // Assume that the user passes in this document as the first argument!
      sav.updateXML(sav.getURL(argv[0]));
      sav.close();
   }
   // Get the connection given the user name and password..!
    private static Connection getConnection(String user, String passwd)
      throws SQLException
    {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn =
          DriverManager.getConnection("jdbc:oracle:oci:@",user,passwd);
     return conn;
   }
}

XSUを使用した削除処理(Java API)

XML文書からの削除の場合は、キー列のリストを指定できます。これらの列は、DELETE文のWHERE句で使用されます。キー列名を指定しない場合、新しいDELETE文がXML文書のROW要素ごとに作成されます。DELETE文のWHERE句の列のリストは、ROW要素の列と一致します。

XMLを削除するXSUの例11: 行ごとの削除操作(Java)

この削除の例を見てみます。

import java.sql.*;
import oracle.xml.sql.dml.OracleXMLSave;
public class testDelete
{
   public static void main(String argv[])
     throws SQLException
   {
      Connection conn = getConnection("hr","hr");
      OracleXMLSave sav = new OracleXMLSave(conn, "hr.employees");

      // Assume that the user passes in this document as the first argument!
      sav.deleteXML(sav.getURL(argv[0]));
      sav.close();
   }
   // Get the connection given the user name and password..!
    private static Connection getConnection(String user, String passwd)
      throws SQLException
    {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn =
          DriverManager.getConnection("jdbc:oracle:oci:@",user,passwd);
     return conn;
   }
}

以前に示した更新の例と同じXML文書を使用して、2つのDELETE文を取得します。

DELETE FROM hr.employees WHERE employee_id=7369 AND salary=1800 AND department_id=30;
DELETE FROM hr.employees WHERE employee_id=2200 AND salary=2000 AND hire_date=12/31/1992;

XML文書内の各ROW要素にあるタグ名に基づいてDELETE文が形成されました。

XMLを削除するXSUの例12: キー値を指定した削除(Java)

かわりにDELETE文の条件としてキー値のみを使用する場合は、setKeyColumnファンクションを使用して設定できます。

import java.sql.*;
import oracle.xml.sql.dml.OracleXMLSave;
public class testDelete
{
   public static void main(String argv[])
     throws SQLException
   {
      Connection conn = getConnection("hr","hr");
      OracleXMLSave sav = new OracleXMLSave(conn, "hr.employees");

      String [] keyColNames = new String[1];
      keyColNames[0] = "EMPLOYEE_ID";
      sav.setKeyColumnList(keyColNames);

      // Assume that the user passes in this document as the first argument!
      sav.deleteXML(sav.getURL(argv[0]));
      sav.close();
   }
   // Get the connection given the user name and password..!
    private static Connection getConnection(String user, String passwd)
      throws SQLException
    {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn =
          DriverManager.getConnection("jdbc:oracle:oci:@",user,passwd);
     return conn;
   }
}

次に、生成された単一のDELETE文を示します。

DELETE FROM hr.employees WHERE employee_id=?

高度なXSUの使用方法

次に、XSUの追加情報を示します。

Javaで処理するXSUの例外

次に例外の処理について説明します。

OracleXMLSQLExceptionクラス

XSUは、処理中に発生したすべての例外を捕捉し、ランタイム例外であるoracle.xml.sql.OracleXMLSQLExceptionを発生させます。プログラムがこの例外を捕捉して適切な処置を実行できる場合、コールするプログラムはこの例外を捕捉する必要はありません。例外クラスには、エラー・メッセージおよび存在する場合は親である例外も取得するための関数があります。たとえば、後ほど示すプログラムでは、ランタイム例外を捕捉してから親である例外を取得します。

OracleXMLNoRowsExceptionクラス

この例外は、setRaiseNoRowsExceptionが生成中にOracleXMLQueryクラスに設定されると生成されます。これはOracleXMLSQLExceptionクラスのサブクラスで、生成中に行処理を終了するインジケータとして使用できます。

import java.sql.*;
import oracle.xml.sql.query.OracleXMLQuery;

public class testException
{
   public static void main(String argv[])
     throws SQLException
   {
      Connection conn = getConnection("hr","hr");

      // wrong query this will generate an exception
      OracleXMLQuery qry = new OracleXMLQuery(conn, "select * from employees
         where sd = 322323");

      qry.setRaiseException(true); // ask it to raise exceptions..!

      try{
        String str = qry.getXMLString();
      }catch(oracle.xml.sql.OracleXMLSQLException e)
      {
        // Get the original exception
        Exception parent = e.getParentException();
        if (parent instanceof java.sql.SQLException)
        {
           // perform some other stuff. Here you simply print it out..
           System.out.println(" Caught SQL Exception:"+parent.getMessage());
        }
        else
          System.out.println(" Exception caught..!"+e.getMessage());
     }
   }
    // Get the connection given the user name and password..!
    private static Connection getConnection(String user, String passwd)
      throws SQLException
    {
      DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
      Connection conn =
          DriverManager.getConnection("jdbc:oracle:oci:@",user,passwd);
     return conn;
   }
}

XML SQL Utility(XSU)の使用のヒント

この項では、XSUのヒントを示します。

XMLを格納するためにXSUで使用するスキーマ構造

customer.xmlファイルに次のXMLがある場合:

<ROWSET>
 <ROW num="1">
  <CUSTOMER>
   <CUSTOMERID>1044</CUSTOMERID>
   <FIRSTNAME>Paul</FIRSTNAME>
   <LASTNAME>Astoria</LASTNAME>
   <HOMEADDRESS>
    <STREET>123 Cherry Lane</STREET>
    <CITY>SF</CITY>
    <STATE>CA</STATE>
    <ZIP>94132</ZIP>
   </HOMEADDRESS>
  </CUSTOMER>
 </ROW>
</ROWSET>

XSUでこのXMLを格納するためにはどのようなデータベース・スキーマ構造を使用できるでしょうか。

この例は複数のレベルの深さ(ネストした構造)であるため、オブジェクト・リレーショナル・スキーマを使用できます。前述のXMLは、このようなスキーマに正規マッピングされます。適切なデータベース・スキーマは次のとおりです。

CREATE TYPE address_type AS OBJECT
 (
 street VARCHAR2(40),
 city VARCHAR2(20),
 state VARCHAR2(10),
 zip VARCHAR2(10)
 );
 /
CREATE TYPE customer_type AS OBJECT
 (
customerid NUMBER(10),
firstname VARCHAR2(20),
lastname VARCHAR2(20),
homeaddress address_type
 );
/
CREATE TABLE customer_tab ( customer customer_type);

XSUを使用してリレーショナル・スキーマにcustomer.xmlをロードする場合、リレーショナル・スキーマの最上位にビューのオブジェクトを作成することによりロードを実行できます。

たとえば、次のすべての情報を含むリレーショナル表があるとします。

CREATE TABLE cust_tab
 ( customerid NUMBER(10),
   firstname VARCHAR2(20),
   lastname VARCHAR2(20),
   street VARCHAR2(40),
   city VARCHAR2(20),
   state VARCHAR2(20),
   zip VARCHAR2(20)
 );

次の例に示すように、最上位にカスタマ・オブジェクトを持つカスタマ・ビューを作成します。

CREATE VIEW customer_view AS
SELECT customer_type(customerid, firstname, lastname,
address_type(street,city,state,zip)) customer
FROM cust_tab;

最後に、XSLTを使用してXMLをフラット化し、このXMLをリレーショナル・スキーマに直接挿入できます。ただし、この方法は、あまりお薦めできません。

XMLデータ・アクセス表の格納

現在XML SQL Utility(XSU)は単一の表にのみデータを格納できます。任意の表またはビューにXML文書の正規の表示をマップします。ただし、XSUを使用して表にまたがってXMLを格納する方法があります。これはXSLTを使用して任意の文書を複数の文書に変換し、これらの文書を別々に挿入することで実行できます。また、(必要に応じてオブジェクト・ビューを使用して)複数の表にまたがるビューを定義してから、ビューに挿入する方法もあります。このビューが更新不可能(複雑な結合などのために)な場合は、ビューにまたがってIINSTEAD OFトリガーを使用して、挿入を実行できます。

属性に格納されたデータのXSUによるロード

XSLTを使用してXML文書を変換する必要があります。つまり、属性を要素に変更する必要があります。XSUがXMLからデータベース・スキーマに正規マッピングすることが前提です。これはやや柔軟性に欠けるため、XSLTを使用することになりますが、その反面、一般的にはマッピングを指定する負担がありません。

XSUの大/小文字の区別

デフォルトでは、XSUには大/小文字の区別があります。2つのオプション(正確な大/小文字を使用するか、またはignoreCase機能を使用する)があります。

XSUを使用してDTDからデータベース・スキーマを生成できない

DTDには多くの短所があるため、データベース・スキーマを生成できません。XML SchemaのW3C勧告は確定していますが、XSUではまだこの機能を使用できません。

XSUのシン・ドライバ接続文字列の例

次に、JDBCシン・ドライバ接続文字列の例を示します。

jdbc:oracle:thin:user/password@hostname:portnumber:DBSID;

さらに、データベースにはアクティブなTCP/IPリスナーが必要です。有効なOCI接続文字列は次のとおりです。

jdbc:oracle:oci:user/password@hostname

INSERT、DELETEまたはUPDATE後のXSUおよびコミット

XML SQL Utilityは挿入、削除または更新後にコミットしますか。エラーが発生した場合はどうなりますか。

デフォルトでは、XSUは一度に多くのINSERT文、DELETE文またはUPDATE文を実行します。バッチ処理で同時に実行される文の数は、setBatchSize機能でオーバーライドできます。

また、デフォルトでは、XSUは明示的なコミットを行いません。AUTOCOMMITが、JDBC接続のデフォルトであるオンになっている場合、文の各バッチを実行した後、コミットが実行されます。AUTOCOMMITをオフにし、setCommitBatch機能を使用して、コミット前に実行する文の数を指定することで、この動作をオーバーライドできます。

エラーが発生した場合は、XSUへの特定のコール前のターゲット表の状態、またはXSUへの現在のコール中に行われた前回のコミット直後の状態にロールバックします。

XSUを使用したXML属性への表の列のマッピング

XSUリリース2.1.0から、特定の列または列のグループをXML要素ではなくXML属性にマップできるようになりました。これを達成するには、列名に別名を作成し、この別名の前にアットマーク(@)を付加します。次に例を示します。

* Create a file called select.sql with the following content :
   SELECT empno "@EMPNO", ename, job, hiredate
   FROM emp
   ORDER BY empno

 * Call the XML SQL Utility :
   java OracleXML getXML -user "scott/tiger" \
           -conn "jdbc:oracle:thin:@myhost:1521:ORCL" \
           -fileName "select.sql"

 * As a result, the XML document will look like :
     <?xml version = '1.0'?>
     <ROWSET>
        <ROW num="1" EMPNO="7369">
           <ENAME>SMITH</ENAME>
           <JOB>CLERK</JOB>
           <HIREDATE>12/17/1980 0:0:0</HIREDATE>
        </ROW>
        <ROW num="2" EMPNO="7499">
           <ENAME>ALLEN</ENAME>
           <JOB>SALESMAN</JOB>
           <HIREDATE>2/20/1981 0:0:0</HIREDATE>
        </ROW>
     </ROWSET>


注意:

すべてのXML属性の列を先にマップする必要があります。

XML文書はストリーム形式で作成されているため、次の問合せの場合、

SELECT ename, empno "@EMPNO", ...

予期した結果は生成されません。現時点で、属性に格納されたXMLデータをロードすることはできません。XSLT変換を使用して属性を要素に変更する必要があります。XSUがXMLからデータベース・スキーマに正規マッピングすることが前提です。