13 XML SQL Utilityの使用

Extensible Markup Language (XML) SQL Utility (XSU)の使用方法について説明します。

トピック:

13.1 XML SQL Utility(XSU)の概要

XML SQL Utility (XSU)は、Oracle SQL文を使用してXMLデータを転送できるようにするOracle XML Developer's Kit (XDK)コンポーネントです。

XML SQL Utility (XSU)を使用して、次のタスクを実行できます。

  • オブジェクト・リレーショナル・データベースの表またはビューのデータをXMLに変換します。XSUは、データベースの問合せを実行し、結果セットをXML文書として戻します。

  • XML文書からデータを抽出し、正規マッピングを使用して、表またはビューへのデータの挿入、適切な列または属性の値を更新または削除できます。

トピック:

13.1.1 XML SQL Utility (XSU)の使用の前提条件

XML SQL Utility (XSU)の使用の前提条件を示します。

この項では、次のテクノロジを十分に理解していると想定しています。

  • Oracle Database Structured Query Language (SQL)。XSUでは、SELECT文およびデータ操作言語(DML)を介してデータベースとの間でXMLを転送します。

  • Procedural Language/Structured Query Language (PL/SQL)。XDKには、Java APIをミラー化するXSU用のPL/SQLアプリケーション・プログラミング・インタフェース(API)が用意されています。

  • Java Database Connectivity (JDBC): XSUを使用してデータベースとの間でXMLの転送を行うJavaアプリケーションには、JDBC接続が必要です。

13.1.2 XSUの機能

XML SQL Utility (XSU)で提供される主な機能について説明します。

XSU:

  • Document Type Definitions (DTD)またはXMLスキーマを動的に生成します。

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

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

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

  • 生成中のXML属性をサポートします。この属性のサポートにより、特定の列または列のグループが、XML要素ではなくXML属性にマップされるように指定できます。

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

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

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

13.1.3 XSUの制限

XSUを使用する際のいくつかの制限について説明します。

  • XSUは、単一表にのみデータを格納できます。ただし、Oracle Extensible Stylesheet Language Transformation (XSLT)プロセッサを使用して文書を複数の文書に変換して個別に挿入することで、複数の表にまたがってXMLを格納できます。また、複数表にまたがるビューを定義し、ビューへの挿入を行うこともできます。このビューが更新不可能(複雑な結合などのために)な場合は、ビューにまたがってINSTEAD OFトリガーを使用して、挿入を実行できます。

  • 属性に格納されたXMLデータはXSUを使用してデータベース・スキーマにロードできませんが、XSLT変換を使用して属性を要素に変更することは可能です。

  • デフォルトでは、XSUには大/小文字の区別があります。正確な大/小文字を使用するか、大/小文字の区別を無視するように指定できます。

  • XSUは、入力DTDからリレーショナル・データベース・スキーマを生成できません。

  • XSUを使用したXMLType表への挿入はサポートされていません。XMLType列はサポートされています。

13.2 XML SQL Utility(XSU)の使用: 概要

このトピックでは、XSUの基本的な使用方法、XSUのインストール、XSUデモ・プログラムの実行、およびXSUコマンドライン・ユーティリティの使用について説明します。

トピック:

13.2.1 XSUの使用: 基本プロセス

XSUの使用の基本プロセスについて説明します。

XSUには、パッケージoracle.xml.sql.queryのJavaクラスOracleXMLQueryおよびOracleXMLSaveを介してアクセスできます。OracleXMLQueryクラスを使用してリレーショナル・データからXMLを生成し、OracleXMLSaveクラスを使用してDMLを実行します。

次のようなタイプのXSUアプリケーションを作成できます。

  • データベース内で実行して内部XSU Java APIにアクセスするJavaプログラム

  • クライアントで実行してクライアント側XSU Java APIにアクセスするJavaプログラム

  • PL/SQLパッケージを介してXSUにアクセスするPL/SQLプログラム

トピック:

13.2.1.1 XSUのJava APIを使用したXMLの生成: 基本プロセス

クラスOracleXMLQueryは、XSUのJava APIのXML生成部分を構成します。

図13-1に、XSUを使用したXMLの生成の基本プロセスを示します。

図13-1の基本手順は次のとおりです。

図13-1 XSUを使用したXMLの生成

図13-1の説明が続きます
「図13-1 XSUを使用したXMLの生成」の説明
  1. データベースへのJDBC接続を作成します。通常では、JDBCドライバのセットを管理するDriverManagerクラスとの接続を確立します。JDBCドライバをロードした後、getConnection()を起動します。適切なドライバが見つかると、このメソッドは、データベース・セッションを表すConnectionオブジェクトを戻します。すべてのSQL文は、このセッションのコンテキスト内で実行されます。

    次のようなオプションがあります。

    • JDBC Oracle Call Interface (OCI)ドライバを使用して接続を作成します。次のコード部分で、この方法を示します。

      // import the Oracle driver class
      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","password");
      

      前述の例では、JDBC OCIドライバのデフォルト接続を使用しています。

    • シンJDBCドライバを使用して接続を作成します。シン・ドライバはPure Javaで作成されており、すべてのJavaプログラムからコールできます。次のコード部分で、この方法を示します。

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

      シン・ドライバには、ホスト名(dlsun489)、ポート番号(1521)およびOracleシステム識別子(SID) ORCLが必要です。データベースにアクティブなTransmission Control Protocol/Internet Protocol (TCP/IP)リスナーが必要です。

    • サーバー側の内部JDBCドライバが使用するデフォルト接続を使用します。このドライバは、デフォルト・セッションおよびデフォルト・トランザクション・コンテキスト内で実行されます。ユーザーはすでにデータベースに接続されているため、ユーザーのSQL操作はデフォルト・トランザクションの一部です。したがって、ドライバを登録する必要はありません。Connectionオブジェクトを作成します。

      Connection conn = new oracle.jdbc.OracleDriver().defaultConnection ();

    注意:

    OracleXMLDataSetExtJdbcはOracle JDBCでのみ使用され、OracleXMLDataSetGenJdbcはOracle以外のJDBCで使用されます。これらのクラスは、oracle.xml.sql.datasetパッケージにあります。

  2. XML問合せオブジェクトを作成し、SQL問合せを割り当てます。コンストラクタにSQL問合せを渡して、OracleXMLQueryクラスのインスタンスを作成します。次に例を示します。
    OracleXMLQuery qry = new OracleXMLQuery (conn, "SELECT * from EMPLOYEES");
    
  3. OracleXMLQueryのメソッドを起動して、XML問合せオブジェクトを構成します。次の例は、結果セットに20行のみ含めることを指定します。
    xmlQry.setMaxRows(20); 
    
  4. OracleXMLQueryのメソッドを起動して、DOMオブジェクトまたは文字列を戻します。たとえば、次のようにしてDOMオブジェクトを取得します。
    XMLDocument domDoc = (XMLDocument)qry.getXMLDOM();
    

    文字列オブジェクトを取得します。

    String xmlString = qry.getXMLString();
    
  5. 必要に応じて、文字列またはDOMに対して追加の処理を行います。

    関連項目:

13.2.1.2 XSUのJava APIを使用したDMLの実行: 基本プロセス

OracleXMLSaveクラスを使用して、データベースのXMLを挿入、更新および削除します。

図13-2に、基本プロセスを示します。

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

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

図13-2の基本手順は次のとおりです。

  1. データベースへのJDBC接続を作成します。この手順は、「XSUのJava APIを使用したXMLの生成: 基本プロセス」で説明している最初の手順と同じです。

  2. XML保存オブジェクトを作成し、DMLを実行するための表を割り当てます。コンストラクタに表名またはビュー名を渡します。次に例を示します。

    OracleXMLSave sav = new OracleXMLSave(conn, "employees");
    
  3. 主キー列を指定します。たとえば、次のコードは、employee_idがキー列であることを指定します。

    String [] keyColNames = new String[1];
    keyColNames[0] = "EMPLOYEE_ID";
    sav.setKeyColumnList(keyColNames);
    
  4. OracleXMLSaveのメソッドを起動して、XML保存オブジェクトを構成します。次の例は、salaryおよびjob_id列の更新を指定します。

    String[] updateColNames = new String[2];
    updateColNames[0] = "SALARY";
    updateColNames[1] = "JOB_ID";
    sav.setUpdateColumnList(updateColNames); // set the columns to update
    
  5. OracleXMLSaveオブジェクトに対してinsertXML()updateXML()またはdeleteXML()メソッドを起動します。次の例では、更新を示します。

    // Assume that the user passes in this XML document as the first argument
    sav.updateXML(sav.getURL(argv[0]));
    

    DMLの実行中に、XSUは次のタスクを行います。

    1. 入力XML文書を解析します。

    2. 要素名をターゲットの表またはビューにある列名と照合します。

    3. 要素をSQL型に変換し、適切な文にバインドします。

  6. OracleXMLSaveオブジェクトをクローズし、関連するすべてのコンテキストを割当て解除します。次に例を示します。

    sav.close();

    関連項目:

13.2.1.3 XSUのPL/SQL APIを使用したXMLの生成: 基本プロセス

XSUのPL/SQL APIは、XML文書の生成およびデータベースへの格納の方法がJava APIに似ています。パッケージDBMS_XMLQueryは、JavaクラスOracleXMLQueryのメソッドを反映しています。

パッケージDBMS_XMLQueryには、それに関連付けられたコンテキスト・ハンドルがあります。コンストラクタに類似したファンクションを起動してコンテキストを作成し、ハンドルを取得してそのハンドルをすべての副問合せの起動に使用します。

注意:

パフォーマンス向上のため、DBMS_XMLQUERYではなく、Cで記述されデータベースに組み込まれたCベースのDBMS_XMLGENの使用を検討してください。

XSUは、XMLTypeデータ型をサポートします。XSUでのXMLTypeの使用は、オブジェクトまたは表内にXMLType列が含まれる場合などに有効です。

XMLを生成すると、XML文書を含むキャラクタ・ラージ・オブジェクト(CLOB)が生成されます。DBMS_XMLQueryおよびXSU生成エンジンを使用するための基本手順は次のとおりです。

  1. XML問合せコンテキストの変数および生成されたXMLの変数を宣言します。次に例を示します。
    v_queryCtx  DBMS_XMLQuery.ctxType;
    v_result    CLOB;
    
  2. DBMS_XMLQuery.newContextファンクションを起動し、CLOBまたはVARCHAR2のいずれかで問合せを指定して、コンテキスト・ハンドルを取得します。次の例では、バインド変数:EMPLOYEE_IDおよび:FIRST_NAMEを含むWHERE句を使用して、employees表から行を選択する問合せを登録します。
    v_queryCtx = DBMS_XMLQuery.newContext('SELECT * FROM employees 
                       WHERE employee_id=:EMPLOYEE_ID AND first_name=:FIRST_NAME');
    
  3. 値を問合せにバインドします。バインドは、名前を位置にバインドすることで行われます。clearBindValuesは、すべてのバインド変数を消去し、setBindValueは、単一のバインド変数に文字列値を設定します。たとえば、employee_idおよびfirst_nameの値を次のようにバインドします。
    DBMS_XMLQuery.setBindValue(v_queryCtx,'EMPLOYEE_ID',20);
    DBMS_XMLQuery.setBindValue(v_queryCtx,'FIRST_NAME','John');
    
  4. 問合せコンテキストを構成します。ROWタグ名、ROWSETタグ名、フェッチする行の数などの引数をオプションで設定します。次の例は、デフォルトのROWSET要素名をEMPSETに変更します。
    DBMS_XMLQuery.setRowSetTag(v_queryCtx,'EMPSET');
    
  5. 結果をフェッチします。getXMLファンクションを使用して、XMLをCLOBとして取得します。このファンクションでは、DTDまたはXMLスキーマの有無にかかわらずXMLを生成できます。次の例は、文にバインド値を適用し、述語employee_id = 20およびfirst_name = 'John'に対応する結果を取得します。
    v_result := DBMS_XMLQuery.getXML(v_queryCtx);
    
  6. XMLの生成結果を処理します。たとえば、プログラムで次の変数を宣言するとします。
    v_xmlstr VARCHAR2(32767);
    v_line   VARCHAR2(2000);
    

    v_resultに格納されたCLOBを次のように出力できます。

    v_xmlstr := DBMS_LOB.SUBSTR(v_result,32767);
    LOOP
      EXIT WHEN v_xmlstr IS NULL;
      v_line := substr(v_xmlstr,1,INSTR(v_xmlstr,CHR(10))-1);
      DBMS_OUTPUT.PUT_LINE('| ' || v_line);
      v_xmlstr := SUBSTR(v_xmlstr,INSTR(v_xmlstr,CHR(10))+1);
    END LOOP;
    
  7. コンテキストをクローズします。次に例を示します。
    DBMS_XMLQuery.closeContext(v_queryCtx);
13.2.1.4 PL/SQL APIを使用したDMLの実行: 基本プロセス

DBMS_XMLSaveは、JavaクラスOracleXMLSaveのメソッドが反映されたPL/SQLパッケージです。このパッケージには、パッケージに対応付けられたコンテキスト・ハンドルがあります。コンストラクタに類似したファンクションを起動してコンテキストを作成し、ハンドルを取得してそのハンドルをすべての副問合せの起動に使用します。

DBMS_XMLSaveを使用するための基本手順は次のとおりです。

  1. XML保存コンテキストの変数およびDML操作の対象となる行数のための変数を宣言します。次に例を示します。
    savCtx DBMS_XMLSave.ctxType;
    v_rows   NUMBER;
    
  2. DBMS_XMLSave.newContextファンクションを起動し、DML操作に使用する表名を指定して、コンテキスト・ハンドルを作成します。
    savCtx  := DBMS_XMLSave.newContext('hr.employees');
    
  3. 実行するDMLの種類に基づいてオプションを設定します。

    挿入の場合は、setUpdateColumnファンクションに挿入する列のリストを設定できます。デフォルトでは、すべての列に値が挿入されます。次の例は、employees表の5つの列を設定します。

    DBMS_XMLSave.setUpdateColumn(savCtx,'EMPLOYEE_ID'); 
    DBMS_XMLSave.setUpdateColumn(savCtx,'LAST_NAME');
    DBMS_XMLSave.setUpdateColumn(savCtx,'EMAIL');
    DBMS_XMLSave.setUpdatecolumn(savCtx,'JOB_ID');
    DBMS_XMLSave.setUpdateColumn(savCtx,'HIRE_DATE');
    

    更新の場合は、キー列のリストを指定する必要があります。オプションで、更新する列のリストも指定できます。この場合は、キー列名と一致するXML文書内のタグがUPDATE文のWHERE句に使用され、更新列のリストと一致するタグがUPDATE文のSET句に使用されます。次に例を示します。

    DBMS_XMLSave.setKeyColumn(savCtx,'employee_id'); -- set key column
    -- set list of columns to update.
    DBMS_XMLSave.setUpdateColumn(savCtx,'salary');
    DBMS_XMLSave.setUpdateColumn(savCtx,'job_id');
    

    削除の場合は、デフォルトで、指定した文書の各<ROW>要素にあるすべてのタグ値と一致するWHERE句が作成されます。この動作は、キー列のリストを設定することでオーバーライドできます。この場合は、タグ名がリスト内の列と一致するタグ値のみが、削除する行の識別に使用されます(DELETE文のWHERE句に使用して有効)。次に例を示します。

    DBMS_XMLSave.setKeyColumn(savCtx,'EMPLOYEE_ID');
    
  4. insertXMLupdateXMLまたはdeleteXMLファンクションのコンテキストおよびXML文書を指定します。次に例を示します。
    v_rows := DBMS_XMLSave.deleteXML(savCtx,xmlDoc);
    
  5. DMLを必要な回数のみ繰り返します。
  6. コンテキストをクローズします。次に例を示します。
    DBMS_XMLSave.closeContext(savCtx);
    

モデルとして、「XSU Java APIを使用したプログラミング」で説明されているJavaの例を使用してください。

13.2.2 XSUのインストール

XSUは、他のXDKユーティリティとともにOracle Databaseの一部として含まれています。

XSUのコンポーネントおよび依存性については、「XDK for Javaコンポーネントの依存性」で説明しています。

デフォルトでは、Oracle Universal Installerによって、XSUがディスク上にインストールされ、データベースにロードされます。ユーザーが介入する必要はありません。OracleをインストールしたときにXSUをデータベースにロードしなかった場合は、次のようにXSUを手動でインストールできます。

  1. Oracle XML DBがインストールされていることを確認します(デフォルトでは、Oracle Databaseの一部としてインストールされます)。
  2. xsu12.jarファイルをデータベースにロードします。このJARファイルには、XMLTypeへのアクセスに関してxdb.jarへの依存性があります。JARファイルの詳細は、表3-1を参照してください。
  3. $ORACLE_HOME/rdbms/admin/dbmsxsu.sqlスクリプトを実行します。このSQLスクリプトは、XSUのPL/SQL APIを構築します。

「XSUの使用: 基本プロセス」で説明しているように、XSUを使用するために、XSUをデータベースにロードする必要はありません。XSUは、Javaをサポートする任意の層に格納できます。

トピック:

13.2.2.1 データベースでのXSU

データベースにインストールされたXSUライブラリを使用するアプリケーションの一般的なアーキテクチャを示します。

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

図13-3では、すべての矢印が両方向です。XSUでは、データを生成および保存できるため、データベース内で実行しているXSUにXMLを配信し、それを適切なデータベース表に挿入できます。

図13-3 データベース内でのXSUの実行

図13-3の説明が続きます
「図13-3 データベース内でのXSUの実行」の説明
13.2.2.2 アプリケーション・サーバーでのXSU

XSUをアプリケーション・サーバーで実行できます。

アプリケーション・アーキテクチャによっては、中間層のアプリケーション・サーバーが必要な場合もあります。アプリケーション層には、Javaプログラムをサポートするデータベースまたはアプリケーション・サーバーを指定できます。

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

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

図13-4 中間層でのXSUの実行

図13-4の説明が続きます
「図13-4 中間層でのXSUの実行」の説明
13.2.2.3 WebサーバーでのXSU

WebサーバーはJavaサーブレットをサポートするため、XSUをWebサーバーで実行できます。

図13-5に、Webサーバー内でのXSUの実行を示します。

図13-5 Webサーバー内でのXSUの実行

図13-5の説明
「図13-5 Webサーバー内でのXSUの実行」の説明

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

関連項目:

13.2.3 XSUのデモ・プログラムの実行

XSUのデモ・プログラムは、$ORACLE_HOME/xdk/demo/java/xsuにあります。

表13-1に、XSUのテストに使用できるXMLファイルとプログラムを示します。

表13-1 XSUのサンプル・ファイル

ファイル 説明

createObjRelSchema.sql

オブジェクト・リレーショナル・スキーマを設定し、データを移入するSQLスクリプト。「オブジェクト・リレーショナル・スキーマでのXMLのマッピング」を参照してください。

createObjRelSchema2.sql

オブジェクト・リレーショナル・スキーマを設定し、データを移入するSQLスクリプト。「データベース・スキーマまたはSQL問合せの変更」を参照してください。

createRelSchema.sql

リレーショナル表を作成し、最上位にカスタマ・オブジェクトを持つカスタマ・ビューを作成するSQLスクリプト。「データベース・スキーマまたはSQL問合せの変更」を参照してください。

customer.xml

カスタマについて記述されたXML文書。「データベース・スキーマまたはSQL問合せの変更」を参照してください。

domTest.java

DOMツリーを生成し、ドキュメント内の順序でツリーを検索して、ノードを1つずつ出力するプログラム。「OracleXMLQueryを使用したDOMツリーの生成」を参照してください。

index.txt

デモ・ディレクトリのプログラムについて説明するREADME。

mapColumnToAtt.sql

employees表に問合せを行って、employee_idをXML属性としてレンダリングするSQLスクリプト。「データベース・スキーマまたはSQL問合せの変更」を参照してください。

new_emp.xml

新しい従業員を記述したXML文書。「testInsertプログラムの実行」を参照してください。

new_emp2.xml

新しい従業員を記述したXML文書。「testInsertSubsetプログラムの実行」を参照してください。

noRowsTest.java

行がなくなると、例外を発生させるプログラム。「該当する行がない場合の例外の生成」を参照してください。

pageTest.java

JDBCのResultSetを使用して、一度に1ページずつXMLを生成するプログラム。「スクロール可能な結果セットの生成」を参照してください。

paginateResults.java

結果ページを区切るXMLページを生成するプログラム。「OracleXMLQueryを使用した結果ページの区切り: 例」を参照してください。

refCurTest.java

testRefCurファンクションで定義されたSQL問合せの結果からXMLを生成するプログラム。「カーソル・オブジェクトからのXMLの生成」を参照してください。

samp1.java

scott.emp表に問合せを行って、問合せ結果からXML文書を生成するプログラム。

samp10.java

samdoc.xmlxmltest_tab1表に挿入するプログラム。

samp2.java

scott.emp表に問合せを行って、問合せ結果からXML文書を生成するプログラム。このプログラムは、生成されたXML文書をカスタマイズする方法を示します。

sampdoc.xml

samp10.javaによってデータベースに挿入されるサンプルXMLデータ文書。

samps.sql

samp10.javaで使用するxmltest_tab1表を作成するSQLスクリプト。

testDeleteKey.java

行の識別のために使用される要素の数を制限し、DELETE文のキャッシュおよびトランザクションのバッチによってパフォーマンスを向上させるプログラム。「OracleXMLSaveを使用したキーによる削除」を参照してください。

testDeleteRow.java

XML文書のファイル名を入力として受け入れ、文書内の要素に対応する行を削除するプログラム。「OracleXMLSaveを使用した行による削除」を参照してください。

testException.java

ランタイム例外をスローし、Exception.getParentException()を起動して親である例外を取得するサンプル・プログラム。「親である例外の取得」を参照してください。

testInsert.java

hr.employees表のすべての列にXML値を挿入するJavaプログラム。「OracleXMLSaveを使用したすべての列へのXMLの挿入」を参照してください。

testInsertSubset.java

XMLデータを列のサブセットに挿入するプログラム。「OracleXMLSaveを使用した列のサブセットへのXMLの挿入」を参照してください。

testRef.sql

REFカーソルを定義し、そのカーソルを戻すファンクションを作成するPL/SQLスクリプト。testRefCurファンクションをコールするたびに、SELECT問合せに対してカーソル・オブジェクトをオープンし、そのカーソル・インスタンスを戻します。「カーソル・オブジェクトからのXMLの生成」を参照してください。

testUpdate.java

OracleXMLSave.setKeyColumnList()メソッドを起動して、hr.employees表を更新するサンプル・プログラム。「OracleXMLSaveを使用した行の更新」を参照してください。

testUpdateList.java

各従業員の給与および役職名のみを更新し、他の情報を無視するとします。XML文書内のすべてのROW要素について、更新対象の要素がすべて同じである場合は、OracleXMLSave.setUpdateColumnNames()メソッドを使用して列を指定できます。「OracleXMLSaveを使用した列リストの更新」を参照してください。

testXMLSQL.java

XSUを使用して、XMLをStringオブジェクトとして生成するサンプル・プログラム。このプログラムはhr.employees表に問合せを行って結果セットを標準出力に出力します。「OracleXMLQueryを使用した文字列の生成」を参照してください。

upd_emp.xml

一連の従業員の更新された給与およびその他の情報を含むXML文書。「testUpdateプログラムの実行」を参照してください。

upd_emp2.xml

一連の従業員の更新された給与およびその他の情報を含むXML文書。「testUpdateプログラムの実行」を参照してください。

updateEmployee.sql

2人の従業員の新規データを含むXML文書。「testUpdateListプログラムの実行」を参照してください。

デモの実行手順は次のとおりです。

  1. ディレクトリを$ORACLE_HOME/xdk/demo/java/xsuディレクトリ(UNIXの場合)または%ORACLE_HOME%\xdk\demo\java\xsuディレクトリ(Windowsの場合)に変更します。
  2. 「XDK for Java環境の設定」の説明に従って、環境変数が設定されていることを確認します。特に、XSUに対してはxsu12.jar、JDBC対してはojdbc6.jar (Java 1.6)がJavaクラスパスに含まれていることを確認してください。UTF-8、ISO8859-1またはJA16SJIS以外のマルチバイト・キャラクタ・セットを使用する場合は、クラスパスにorai18n.jarを置いて、JDBCが入力ファイルのキャラクタ・セットをデータベースのキャラクタ・セットに変換できるようにします。
  3. 次の例のように、Javaプログラムをコンパイルします。
    javac samp1.java samp2.java samp10.java
    
  4. ユーザーhrとしてデータベースに接続し、SQLスクリプトcreateRelSchemaを実行します。
    CONNECT hr
    @$ORACLE_HOME/xdk/demo/java/xsu/createRelSchema
    

次の項では、XSUのデモについて詳しく説明します。

13.2.4 XSUコマンドライン・ユーティリティの使用

XDKには、XSUのためのコマンドラインJavaインタフェースがあります。XSUのコマンドライン・オプションは、JavaクラスOracleXMLを介して利用できます。

このAPIを使用するには、「XDK for Java環境の設定」の説明に従ってJavaクラスパスが設定されていることを確認します。

XSUの使用情報を標準出力に出力するには、次のコマンドを実行します。

java OracleXML

XSUを使用するには、次のようにgetXMLまたはputXMLのいずれかのパラメータを使用して起動します。

java OracleXML getXML options
java OracleXML putXML options

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

表13-2 getXMLオプション

getXMLオプション 説明

-user "username/password"

データベースに接続するためのユーザー名およびパスワードを指定します。接続文字列も指定されます。ユーザー名およびパスワードを接続文字列の一部として指定できます。

-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

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

-collectionIdAttr collect_id_attr_name

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

-useTypeForCollElemTag

column-elementタグに使用する型名を指定します。デフォルトでは、XSUはcolumn-name_itemを使用します。

-useNullAttrId

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

-styleSheet stylesheet_URI

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

-stylesheetType stylesheet_type

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

-setXSLT URI

XML文書に適用するXSLTスタイルシートを指定します。

-setXSLTRef URI

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

-useLowerCase | -useUpperCase

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

-withEscaping

SQLオブジェクト名では有効であっても、XMLタグでは無効な文字の対処方法を指定します。このような文字を検出した場合は、エスケープして例外を発生させません。

-errorTag error tag_name

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

-raiseException

XSUがJava例外を発生させることを指定します。デフォルトでは、XSUがエラーを捕捉し、XMLエラーを発行します。

-raiseNoRowsException

行が戻されなかった場合に例外を発生させます。

-useStrictLegalXMLCharCheck

入力データに対して厳密なチェックを行います。

-maxRows maximum_rows

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

-skipRows number_of_rows_to_skip

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

-encoding encoding_name

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

-dateFormat date_format

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

-fileName SQL_query_fileName | SQL_query

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

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

表13-3 putXMLオプション

putXMLオプション 説明

-user "username/password"

データベースに接続するためのユーザー名およびパスワードを指定します。接続文字列も指定されます。ユーザー名およびパスワードを接続文字列の一部として指定できます。

-conn "JDBC_connect_string"

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

-batchSize batching_size

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

-commitBatch commit_size

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

-rowTag tag_name

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

-dateFormat date_format

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

-withEscaping

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

-ignoreCase

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

-preserveWhitespace

挿入されるXML文書内の空白を保持します。

-setXSLT URI

挿入前にXML文書に適用するXSLTを指定します。

-setXSLTRef URI

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

-fileName file_name | -URL URL | -xmlDoc xml_document

挿入するXML文書を指定します。ローカル・ファイル、URLまたはXML文書をコマンドライン上の文字列として指定します。

table_name

値を挿入する表の名前を指定します。

トピック:

13.2.4.1 XSUコマンドライン・ユーティリティを使用したXMLの生成

データベース・スキーマからXMLを生成するには、getXMLパラメータを使用します。

たとえば、hrスキーマにあるemployees表に問合せを行ってXML文書を生成するには、次の構文を使用できます。

java OracleXML getXML -user "hr/password" "SELECT * FROM employees"

前述のコマンドによって次のタスクが実行されます。

  1. 現在のデフォルト・データベースへの接続
  2. 指定されたSELECT問合せの実行
  3. SQL結果のXMLへの変換
  4. 標準出力へのXMLの出力

getXMLパラメータは、表13-2に示した広範囲なオプションをサポートします。

13.2.4.2 XSUコマンドライン・ユーティリティを使用したXMLTypeデータの生成

XSUを使用して、XMLType列を持つ表からXMLを生成できます。

デモ・スクリプトsetup_xmltype.sqlを実行してparts表を作成し、表にデータを挿入するとします。XSUを使用してこの表からXMLを生成できます。

java OracleXML getXML -user "hr/password" -rowTag "Part" "SELECT * FROM parts"

次にコマンドの出力を示します。

<?xml version = '1.0'?>
<ROWSET>
   <Part num="1">
      <PARTNO>1735</PARTNO>
      <PARTNAME>Gizmo</PARTNAME>
      <PARTDESC>
         <Description>
           <Title>Description of the Gizmo</Title>
           <Author>John Smith</Author>
           <Body>
             The <b>Gizmo</b> is <i>grand</i>.
           </Body>
         </Description>
      </PARTDESC>
   </Part>
</ROWSET>
13.2.4.3 XSUコマンドライン・ユーティリティを使用したDMLの実行

次の例は、XML文書をデータベース表に挿入する方法を示しています。

new_employees.xmlというXML文書をhr.employees表に挿入するには、次の構文を使用します。

java OracleXML putXML -user "hr/password" -fileName "new_employees.xml" employees

前述のコマンドによって次のタスクが実行されます。

  1. hrとして現在のデータベースに接続
  2. new_emp.xmlというXML文書の読取り
  3. タグと列名を一致させてXML文書を解析
  4. employees表への値の適切な挿入

getXMLパラメータは、表13-2に示した広範囲なオプションをサポートします。

13.3 XSU Java APIを使用したプログラミング

このトピックでは、OracleXMLQueryおよびOracleXMLSaveを使用した様々な操作の実行、およびXSU Java例外の処理について説明します。

トピック:

13.3.1 OracleXMLQueryを使用した文字列の生成

testXMLSQL.javaデモ・プログラムは、XSUを使用してXMLをStringオブジェクトとして生成します。このプログラムは、表hr.employeesを問い合せて結果セットを標準出力に出力します。

testXMLSQL.javaプログラムは次の手順を実行します。

  1. JDBCドライバを登録し、データベース接続を作成します。次のコード部分は、OCI JDBCドライバを使用し、ユーザー名hrで接続します。
    import oracle.jdbc.*;...Connection conn  = getConnection("hr","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;
    }
    
  2. XML問合せオブジェクトを作成し、SQL問合せを使用して初期化します。次のコード部分は、hr.employeesに対するSELECT文を使用してオブジェクトを初期化します。
    OracleXMLQuery qry = new OracleXMLQuery(conn, "SELECT * FROM employees");
    
  3. 問合せの結果セットをStringオブジェクトとして取得します。getXMLString()メソッドは、コンストラクタで指定されたオブジェクト・リレーショナル・データをXMLに変換します。次の例では、次の方法を示します。
    String str = qry.getXMLString();
    
  4. 次のコードに示すように、問合せオブジェクトをクローズしてすべてのリソースを解放します。
    qry.close();

トピック:

13.3.1.1 testXMLSQLプログラムの実行

testXMLSQLプログラムについて説明します。

次の手順に従って、testXMLSQL.javaプログラムを実行します。

  1. javacを使用してtestXMLSQL.javaをコンパイルします。
  2. コマンドラインでjava testXMLSQLを実行します。

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

<?xml version = '1.0'?>
<ROWSET>
   <ROW num="1">
      <EMPLOYEE_ID>100</EMPLOYEE_ID>
      <FIRST_NAME>Steven</FIRST_NAME>
      <LAST_NAME>King</LAST_NAME>
      <EMAIL>SKING</EMAIL>
      <PHONE_NUMBER>515.123.4567</PHONE_NUMBER>
      <HIRE_DATE>6/17/1987 0:0:0</HIRE_DATE>
      <JOB_ID>AD_PRES</JOB_ID>
      <SALARY>24000</SALARY>
      <DEPARTMENT_ID>90</DEPARTMENT_ID>
   </ROW>
<!-- ROW num="2" through num="107" ... -->
</ROWSET>

13.3.2 OracleXMLQueryを使用したDOMツリーの生成

XSUが生成したXMLからDOMツリーを生成するには、XSUにDOM文書を直接リクエストします。この方法は、XML文書の文字列表現を作成するオーバーヘッドを伴わずに、XML文書を解析してDOMツリーを生成します。

XSUは、Oracle XML Parserを起動してデータ値からDOMツリーを構築します。domTest.javaデモ・プログラムは、DOMツリーを生成し、ドキュメント内の順序でツリーを検索して、ノードを1つずつ出力します。

domTest.javaプログラムの最初の2つの手順は、「OracleXMLQueryを使用した文字列の生成」testXMLSQL.javaプログラムと同じです。プログラムは次のように続行します。

  1. getXMLDOM()メソッドを起動してDOMを取得します。次の例に、この方法を示します。
    XMLDocument domDoc = (XMLDocument)qry.getXMLDOM();
    
  2. DOMツリーを出力します。標準出力に出力するためのコードは次のとおりです。
    domDoc.print(System.out);
    

    次のようにStringWriterを作成し、PrintWriter内にラップすることもできます。

    StringWriter s = new StringWriter(10000);
    domDoc.print(new PrintWriter(s));
    System.out.println(" The string version ---> \n"+s.toString());
    

プログラムをコンパイルした後、次のようにコマンドラインから実行します。

java domTest

13.3.3 OracleXMLQueryを使用した結果ページの区切り

このトピックでは、結果セット内の行数の制限、ユーザーのセッション期間にわたってオブジェクトのオープン状態を保持する方法、およびOracleXMLQueryを使用した結果のページ区切りについて説明します。

トピック:

13.3.3.1 結果セット内の行数の制限

結果セット内の行数を制限する様々な方法について説明します。

testXMLSQL.javaおよびdomTest.javaで、XSUは問合せによって戻されたすべての行からXMLを生成しました。一度に100行のみ必要であるとき、1000行を含む表に問合せを行う場合を考えます。これには、1つの問合せを実行して最初の100行を取得し、別の問合せによって次の100行を取得し、100行ずつ取得していく方法があります。この方法では、問合せの最初の5行をスキップして結果を生成することはできません。この問題を回避するには、次のJavaメソッドを使用します。

  • OracleXMLSave.setSkipRows()を使用すると、必要な行数を強制的にスキップして結果を生成できます。このメソッドと同等の効果を持つコマンドラインは、-skipRowsパラメータです。

  • OracleXMLSave.setMaxRows()を使用すると、XMLに変換される行数を制限できます。このメソッドと同等の効果を持つコマンドラインは、-maxRowsパラメータです。

例13-1では、skipRowsの値を5に設定し、maxRowsの値を1に設定します。これによって、hr.employees表に問合せを行うと、XSUは最初の5行をスキップしてから次の行のXMLを生成します。

次にサンプル出力を示します(問合せ結果セットの6行目のみが戻されます)。

<?xml version = '1.0'?>
<ROWSET>
   <ROW num="6">
      <EMPLOYEE_ID>105</EMPLOYEE_ID>
      <FIRST_NAME>David</FIRST_NAME>
      <LAST_NAME>Austin</LAST_NAME>
      <EMAIL>DAUSTIN</EMAIL>
      <PHONE_NUMBER>590.423.4569</PHONE_NUMBER>
      <HIRE_DATE>6/25/1997 0:0:0</HIRE_DATE>
      <JOB_ID>IT_PROG</JOB_ID>
      <SALARY>4800</SALARY>
      <MANAGER_ID>103</MANAGER_ID>
      <DEPARTMENT_ID>60</DEPARTMENT_ID>
   </ROW>
</ROWSET>

例13-1 コマンドラインでのskipRowsおよびmaxRowsの指定

java OracleXML getXML -user "hr/password" -skipRows 5 -maxRows 1 \
  "SELECT * FROM employees"
13.3.3.2 ユーザーのセッション期間にわたるオブジェクトのオープン状態の保持

状況によっては、問合せオブジェクトをユーザーのセッション中オープンにしておくことが必要な場合があります。maxRows()メソッドおよびkeepObjectOpen()メソッドを使用すると、このような状況に対処できます。

検索の結果をページ区切りの形式にするWeb検索エンジンについて考えてみます。これらのエンジンでは、最初のページに10個の結果、次のページに次の10個のように結果が表示されます。XSUでこのタスクを実行するには、一度に10行ずつリクエストし、ResultSetをオープン状態にしておきます。こうするとXSUは、次に追加の結果をリクエストされたときに、前回の生成が終了した箇所から生成を開始します。OracleXMLQueryでは、SQL問合せ文字列から結果セットを作成すると、それ以上の結果が必要でないと想定して、通常ではResultSetを内部的にクローズします。したがって、keepObjectOpen()を起動してカーソルをアクティブにしておく必要があります。

行数または行内の列数が多すぎる場合もオープンな問合せオブジェクトが必要になります。この場合は、1つの大きな文書を生成するのではなく、複数の小さな文書を生成できます。

13.3.3.3 OracleXMLQueryを使用した結果ページの区切り: 例

paginateResults.javaプログラムは、結果ページを区切り形式にするXMLページの生成方法を示します。出力されるXMLでは、hr表が20行のみ表示されます。

paginateResults.javaプログラムは、結果ページを区切り形式にするXMLページの生成方法を示します。出力されるXMLでは、hr表が20行のみ表示されます。

paginateResults.javaプログラムの最初の手順では、testXMLSQL.javaの場合と同様に、接続を作成します。このプログラムの処理の続きは次のとおりです。

  1. SQL文オブジェクトを作成し、SQL問合せを使用して初期化します。次のコード部分は、java.sql.ResultSetの2つのオプションを設定します。
    Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, 
                                          ResultSet.CONCUR_READ_ONLY);
    
  2. 問合せを文字列として作成し、Statement.executeQuery()を起動して問合せを実行します。ResultSet型のオブジェクトが戻されます。次の例に、この方法を示します。
    String sCmd = "SELECT first_name, last_name FROM hr.employees"; 
    ResultSet rs = stmt.executeQuery(sCmd); 
    
  3. 次のコードに示すような問合せオブジェクトを作成します。
    OracleXMLQuery xmlQry = new OracleXMLQuery(conn, rs);
    
  4. 問合せオブジェクトを構成します。次のコードは、セッションの期間中に問合せオブジェクトがオープンであることを指定します。また、戻される行数を20行に制限しています。
    xmlQry.keepObjectOpen(true); 
    xmlQry.setRowsetTag("ROWSET"); 
    xmlQry.setRowTag("ROW"); 
    xmlQry.setMaxRows(20); 
    
  5. 結果をStringとして取得し、出力します。
    String sXML = xmlQry.getXMLString(); 
    System.out.println(sXML);
    

プログラムをコンパイルした後、次のようにコマンドラインから実行します。

java paginateResults

13.3.4 スクロール可能な結果セットの生成

問合せを実行して、結果セットの中から、前のページの結果を取得することが必要になる場合があります。スクロールを使用可能にするには、Oracle.jdbc.ResultSetクラスをインスタンス化します。このスクロール可能なResultSetオブジェクトを使用して結果セット内を移動し、移動するたびにXSUを使用してXMLを生成できます。

pageTest.javaプログラムは、JDBCのResultSetを使用して一度に1ページずつXMLを生成する方法を示します。ResultSetは、バッチ・サイズの設定や値のバインドなど、XSUで直接処理されない操作のときに使用する必要があります。

pageTest.javaプログラムは、pageTestオブジェクトを作成し、SQL問合せを使用して初期化します。pageTestオブジェクトのコンストラクタは、次の手順を実行します。

  1. paginateResults.javaに定義された同じgetConnection()メソッドを起動して、JDBC接続を作成します。
    Connection conn;
    ...
    conn  = getConnection("hr","password");
    
  2. 文を作成します。
    Statement stmt;
    ...
    stmt = conn.createStatement();
    
  3. コンストラクタに渡される問合せを実行して、スクロール可能な結果セットを取得します。次のコード部分は、この方法を示します。
    ResultSet rset = stmt.executeQuery(sqlQuery);
    
  4. 接続への参照および結果セット・オブジェクトをコンストラクタに渡して、問合せオブジェクトを作成します。次のコード部分は、この方法を示します。
    OracleXMLQuery qry;
    ...
    qry = new OracleXMLQuery(conn,rset); 
    
  5. 問合せオブジェクトを構成します。次のコードコード部分は、問合せオブジェクトをオープン状態で保持し、行がなくなったときに問合せオブジェクトに例外を発生させます。
    qry.keepObjectOpen(true);
    qry.setRaiseNoRowsException(true);
    qry.setRaiseException(true);
    
  6. 文字列"SELECT * FROM employees"を渡して問合せオブジェクトを作成した後、プログラムは結果セット内をループします。getResult()メソッドは、セットの開始行と終了行を指定する整数値を受け取ります。これは、受け取った値の差を計算して取得する最大行数を設定し、結果を文字列として取得します。次のwhileループは、一度に10行ずつ取得し、出力します。
    int i = 0;
    while ((str = test.getResult(i,i+10))!= null)
    {
      System.out.println(str);
      i+= 10;
    }
    

プログラムをコンパイルした後、次のようにコマンドラインから実行します。

java pageTest

13.3.5 カーソル・オブジェクトからのXMLの生成

CallableStatementオブジェクトを初期化し、カーソル変数を戻すPL/SQLファンクションを実行し、OracleResultSetオブジェクトを取得し、それをOracleXMLQueryオブジェクトに送信して必要なXMLデータを取得できます。

クラスOracleXMLQueryは、問合せ文字列またはResultSetオブジェクトに対してのみXML変換を行います。プログラムがPL/SQLプロシージャを使用し、このプロシージャがREFカーソルを戻す場合の変換方法を考えてみます。「スクロール可能な結果セットの生成」で説明したResultSet変換メカニズムを使用できます。

REFカーソルは、PL/SQL内のカーソル・オブジェクトへの参照です。これらのカーソル・オブジェクトは、一連の値を取得するためにプログラムで繰り返し処理されるSQL文です。これらのカーソル・オブジェクトは、JavaではOracleResultSetオブジェクトに変換されます。Javaプログラムで、CallableStatementオブジェクトを初期化し、カーソル変数を戻すPL/SQLファンクションを実行し、OracleResultSetオブジェクトを取得したら、それをOracleXMLQueryオブジェクトに送信して必要なXMLを取得できます。

testRef.sqlスクリプトで定義されたtestRef PL/SQLパッケージについて考えてみます。これは、REFカーソルを定義するファンクションを作成して戻します。testRefCur PL/SQLファンクションは、コールされるたびにSELECT問合せに対してカーソル・オブジェクトをオープンし、そのカーソル・インスタンスを戻します。オブジェクトをXMLに変換するには、次のようにします。

  1. testRef.sqlスクリプトを実行してhrスキーマ内にtestRefパッケージを作成します。
  2. refCurTest.javaプログラムをコンパイルおよび実行し、testRefCurファンクションに定義されたSQL問合せの結果からXMLを生成します。

スタイルシートを適用するには、applyStylesheetコマンドを使用して、出力を生成する前にスタイルシートを強制的に適用します。

13.3.6 OracleXMLSaveを使用した行の挿入

表またはビューに文書を挿入するには、表名またはビュー名と文書を指定します。XSUは、文書を解析して、値のバインド先のINSERT文を作成します。デフォルトでは、XSUは値を表またはビューのすべての列に挿入します。

存在しない要素は、NULL値として処理されます。次の例では、hr.employees表から生成したXML文書を表に格納する方法を示します。

トピック:

13.3.6.1 OracleXMLSaveを使用したすべての列へのXMLの挿入

testInsert.javaデモ・プログラムは、hr.employees表のすべての列にXML値を挿入します。

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

  1. JDBC/OCI接続を作成します。このプログラムは、この章にある前述の例で使用しているのと同じgetConnection()メソッドを起動します。
    Connection conn = getConnection("hr","password");
    
  2. XML保存オブジェクトを作成します。Connectionの参照およびDML実行対象の表の名前を渡して、オブジェクトを初期化します。次の例に、この方法を示します。
    OracleXMLSave sav = new OracleXMLSave(conn, "employees");
    
  3. 入力XML文書内のデータをhr.employees表に挿入します。次のコード部分は、コマンドラインで指定された文書ファイル名からURLを作成します。
    sav.insertXML(sav.getURL(argv[0]));
    
  4. 次のようにXML保存オブジェクトをクローズします。
    sav.close();

トピック:

13.3.6.1.1 testInsertプログラムの実行

testInsertプログラムについて説明します。

従業員IDが7369の新しい従業員Janet Smithについてnew_emp.xml文書を作成する場合を考えます。次のように、ファイル名new_emp.xmlを引数としてtestInsertプログラムに渡します。

java testInsert "new_emp.xml"

指定した列の値を含む新しい行がemployees表に挿入されます。行要素内に存在しない要素は、NULLとして扱われます。

プログラムを実行すると、次の形式のINSERT文が生成されます。

INSERT INTO hr.employees 
  (employee_id, first_name, last_name, email, phone_number, hire_date, 
   salary, commission_pct, manager_id, department_id)
VALUES
  (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);     

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

13.3.6.2 OracleXMLSaveを使用した列のサブセットへのXMLの挿入

値を挿入する必要がない列がある場合もあります。たとえば、取得する値が完全なセットではなく、残りの列のためにトリガーまたはデフォルト値を使用する必要がある場合などです。

testInsertSubset.javaデモ・プログラムは、その処理の方法を示します。次の手順が実行されます。

  1. JDBC/OCI接続を作成します。このプログラムは、この章にある前述の例で使用しているのと同じgetConnection()メソッドを起動します。
    Connection conn = getConnection("hr","password");
    
  2. XML保存オブジェクトを作成します。Connectionの参照およびDMLを実行する表名を渡して、オブジェクトを初期化します。次の例に、この方法を示します。
    OracleXMLSave sav = new OracleXMLSave(conn, "employees");
    
  3. 文字列の配列を作成します。配列の各要素は、値が挿入される列の名前を指定します。次のコード部分は、列の名前を5つ指定します。
    String [] colNames = new String[5];
    colNames[0] = "EMPLOYEE_ID";
    colNames[1] = "LAST_NAME";
    colNames[2] = "EMAIL";
    colNames[3] = "JOB_ID";
    colNames[4] = "HIRE_DATE";
    
  4. 指定した列を更新するためのXML保存オブジェクトを構成します。次の文は、OracleXMLSave.setUpdateColumnList()メソッドに、配列への参照を渡します。
    sav.setUpdateColumnList(colNames);
    
  5. 入力XML文書内のデータをhr.employees表に挿入します。次のコード部分は、コマンドラインで指定された文書ファイル名からURLを作成します。
    sav.insertXML(sav.getURL(argv[0]));
    
  6. 次のようにXML保存オブジェクトをクローズします。
    sav.close();

トピック:

13.3.6.2.1 testInsertSubsetプログラムの実行

testInsertSubsetプログラムについて説明します。

new_emp2.xml文書を使用して、従業員IDが7400の新しい従業員Adamsのデータを格納する場合を考えます。次のように、new_emp2.xmlを引数としてtestInsertプログラムに渡します。

java testInsert new_emp2.xml

入力ファイルに指定されていない列の値は、無視されます。入力に含まれる各ROW要素のINSERTが実行され、INSERT文はデフォルトでバッチ処理されます。

このプログラムで生成されるINSERT文は次のとおりです。

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

13.3.7 OracleXMLSaveを使用した行の更新

次の例は、表またはビューのフィールドの更新方法を示しています。表またはビュー名とXML文書を指定します。XSUは文書を解析し(文字列が指定されている場合)、1つ以上のUPDATE文を作成して、この文にすべての値をバインドします。

次の例では、XML文書を使用して表hr.employeesを更新します。

トピック:

13.3.7.1 OracleXMLSaveを使用したキー列の更新

デモ・プログラムtestUpdate.javaは、メソッドOracleXMLSave.setKeyColumnList()を起動して表hr.employeesを更新します。

testUpdate.javaは、次の手順に従います。

  1. JDBC/OCI接続を作成します。このプログラムは、この章にある前述の例で使用しているのと同じgetConnection()メソッドを起動します。
    Connection conn = getConnection("hr","password");
    
  2. XML保存オブジェクトを作成します。Connectionの参照およびDML実行対象の表の名前を渡して、オブジェクトを初期化します。次の例に、この方法を示します。
    OracleXMLSave sav = new OracleXMLSave(conn, "employees");
    
  3. 単一要素のString配列を作成して、更新する表の主キー列の名前を保持します。次のコード部分は、employee_id列の名前を指定します。
    String [] keyColNames = new String[1];
    colNames[0] = "EMPLOYEE_ID";
    
  4. XML保存オブジェクトを配列内に指定された主キーに設定します。次の文は、OracleXMLSave.setKeyColumnList()メソッドに、keyColNames配列への参照を渡します。
    sav.setKeyColumnList(keyColNames);
    
  5. 入力XML文書内に指定された行を更新します。次の文は、コマンドラインで指定されたファイル名からURLを作成します。
    sav.updateXML(sav.getURL(argv[0]));
    
  6. 次のようにXML保存オブジェクトをクローズします。
    sav.close();

トピック:

13.3.7.1.1 testUpdateプログラムの実行

testUpdateプログラムについて説明します。

XSUを使用して、表内の指定したフィールドを更新できます。例13-2upd_emp.xmlには、追加した2人の従業員、7369および7400の更新済の給与およびその他の情報が含まれます。

更新の場合は、UPDATE文のWHERE句に、キー列の名前のリストを指定します。hr.employees表では、employee_id列がキーです。

次のように、前述のプログラムにファイル名upd_emp.xmlを引数として渡します。

java testUpdate upd_emp.xml

このプログラムは、2つのUPDATE文を生成します。最初のROW要素には、SALARYフィールドを更新するためのUPDATE文が次のように生成されます。

UPDATE hr.employees SET salary = 3250 WHERE employee_id = 7400;

2番目のROW要素には、次の文が生成されます。

UPDATE hr.employees SET job_id = 'SA_REP' AND MANAGER_ID = 145 
  WHERE employee_id = 7369;

例13-2 upd_emp.xml

<?xml version='1.0'?>
<ROWSET>
 <ROW num="1">
    <EMPLOYEE_ID>7400</EMPLOYEE_ID>
    <SALARY>3250</SALARY>
 </ROW>
 <ROW num="2">
    <EMPLOYEE_ID>7369</EMPLOYEE_ID>
    <JOB_ID>SA_REP</JOB_ID>
    <MANAGER_ID>145</MANAGER_ID>
 </ROW>
<!-- additional rows ... -->
</ROWSET>
13.3.7.2 OracleXMLSaveを使用した列リストの更新

列のリストを指定して、XML文書内の要素のサブセットのみを使用して表を更新できます。XSUはすべてのROW要素に対してバインド変数を持つ同じUPDATE文を使用するため、これは処理が速くなります。文書内にある他のタグを無視できます。

注意:

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

各従業員の給与および役職名を更新し、他のデータを無視するとします。XML文書内のすべてのROW要素について、更新対象の要素がすべて同じである場合は、OracleXMLSave.setUpdateColumnNames()メソッドを使用して列を指定できます。testUpdateList.javaプログラムではこの方法を示します。

testUpdateList.javaプログラムは次の手順を実行します。

  1. JDBC/OCI接続を作成します。このプログラムは、この章にある前述の例で使用しているのと同じgetConnection()メソッドを起動します。
    Connection conn = getConnection("hr","password");
    
  2. XML保存オブジェクトを作成します。Connectionの参照およびDML実行対象の表の名前を渡して、オブジェクトを初期化します。次の例に、この方法を示します。
    OracleXMLSave sav = new OracleXMLSave(conn, "employees");
    
  3. String型の配列を作成して、更新する表の主キー列の名前を保持します。配列には、更新する表の主キー列の名前を持つ1つの要素のみ指定します。次のコード部分は、employee_id列の名前を指定します。
    String [] colNames = new String[1];
    colNames[0] = "EMPLOYEE_ID";
    
  4. XML保存オブジェクトを配列内に指定された主キーに設定します。次の文は、OracleXMLSave.setKeyColumnList()メソッドにcolNames配列への参照を渡します。
    sav.setKeyColumnList(keyColNames);
    
  5. String型の配列を作成して、更新する列の名前を保持します。次のコード部分は、employee_id列の名前を指定します。
    String[] updateColNames = new String[2];
    updateColNames[0] = "SALARY";
    updateColNames[1] = "JOB_ID";
    
  6. XMLの保存オブジェクトに更新する列のリストを設定します。このタスクを実行する文は次のとおりです。
    sav.setUpdateColumnList(updateColNames);
    
  7. 入力XML文書内に指定された行を更新します。次のコード部分は、コマンドラインで指定されたファイル名からURLを作成します。
    sav.updateXML(sav.getURL(argv[0]));
    
  8. 次のようにXML保存オブジェクトをクローズします。
    sav.close();

トピック:

13.3.7.2.1 testUpdateListプログラムの実行

testUpdateListプログラムについて説明します。

サンプルXML文書upd_emp2.xmlを使用して、従業員IDが100のSteven Kingおよび従業員識別子(ID)が206のWilliam Gietzの新しいデータを格納する場合を考えます。次のように、upd_emp2.xmlを引数としてtestUpdateListプログラムに渡します。

java testUpdateList upd_emp2.xml

この例では、プログラムが2つのUPDATE文を生成します。最初のROW要素には、次の文が生成されます。

UPDATE hr.employees SET salary = 8350 AND job_id = 'AC_ACCOUNT' 
  WHERE employee_id = 100;

2番目のROW要素には、次の文が生成されます。

UPDATE hr.employees SET salary = 25000 AND job_id = 'AD_PRES' 
  WHERE employee_id = 206;

13.3.8 XSUを使用した行の削除

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

DELETE文のWHERE句にある列のリストと、ROW要素にある列は一致します。

トピック:

13.3.8.1 OracleXMLSaveを使用した行による削除

testDeleteRow.javaデモ・プログラムは、XML文書のファイル名を入力として受け入れ、文書内の要素に対応する行を削除します。

testDeleteRow.javaプログラムは次の手順を実行します。

  1. JDBC/OCI接続を作成します。このプログラムは、この章にある前述の例で使用しているのと同じgetConnection()メソッドを起動します。
    Connection conn = getConnection("hr","password");
    
  2. XML保存オブジェクトを作成します。Connectionの参照およびDML実行対象の表の名前を渡して、オブジェクトを初期化します。次の例に、この方法を示します。
    OracleXMLSave sav = new OracleXMLSave(conn, "employees");
    
  3. 入力XML文書内で指定された行を削除します。次のコード部分は、コマンドラインで指定されたファイル名からURLを作成します。
    sav.deleteXML(sav.getURL(argv[0]));
    
  4. 次のようにXML保存オブジェクトをクローズします。
    sav.close();

トピック:

13.3.8.1.1 testDeleteプログラムの実行

testDeleteプログラムについて説明します。

この項では、「OracleXMLSaveを使用した行の挿入」で追加した従業員7400および7369を削除する方法を示します。

この例を正しく実行するには、データベースに接続し、hr.job_history表に対する制約を無効にします。

CONNECT hr
ALTER TABLE job_history
  DISABLE CONSTRAINT JHIST_EMP_FK;
EXIT

次のように、testDeleteRowプログラムにupd_emp.xmlを渡します。

java testDeleteRow upd_emp.xml

XML文書内の各ROW要素にあるタグ名に基づいて、DELETE文が構成されます。次の文が実行されます。

DELETE FROM hr.employees WHERE salary = 3250 AND employee_id = 7400;
DELETE FROM hr.employees WHERE job_id = 'SA_REP' AND MANAGER_ID = 145 
  AND employee_id = 7369;
13.3.8.2 OracleXMLSaveを使用したキーによる削除

DELETE文の述語としてキー値のみを使用する場合は、OracleXMLSave.setKeyColumnList()メソッドを起動します。行の識別に使用する要素の数を制限するこの方法には、DELETE文をキャッシュし、トランザクションをバッチ化することによるパフォーマンス向上という利点があります。testDeleteKey.javaプログラムではこの方法を示します。

testDeleteKey.javaプログラムは次の手順を実行します。

  1. JDBC/OCI接続を作成します。このプログラムは、この章にある前述の例で使用しているのと同じgetConnection()メソッドを起動します。
    Connection conn = getConnection("hr","password");
    
  2. XML保存オブジェクトを作成します。Connectionの参照およびDML実行対象の表の名前を渡して、オブジェクトを初期化します。次の例に、この方法を示します。
    OracleXMLSave sav = new OracleXMLSave(conn, "employees");
    
  3. String型の配列を作成して、表の主キー列の名前を保持します。この配列には、1つの要素のみ指定します。次のコード部分は、employee_id列の名前を指定します。
    String [] colNames = new String[1];
    colNames[0] = "EMPLOYEE_ID";
    
  4. XML保存オブジェクトを配列内に指定された主キーに設定します。次の文は、OracleXMLSave.setKeyColumnList()メソッドにcolNames配列への参照を渡します。
    sav.setKeyColumnList(keyColNames);
    
  5. 入力XML文書内で指定された行を削除します。次のコード部分は、コマンドラインで指定されたファイル名からURLを作成します。
    sav.deleteXML(sav.getURL(argv[0]));
    
  6. 次のようにXML保存オブジェクトをクローズします。
    sav.close();

トピック:

13.3.8.2.1 testDeleteKeyプログラムの実行

testDeleteKeyプログラムについて説明します。

この項では、「OracleXMLSaveを使用したキー列の更新」で追加した従業員7400および7369を削除する方法を示します。前述の例でこれらの従業員が削除されている場合は、次のように、これらの従業員をemployees表に再び追加できます。

java testInsert new_emp.xml
java testInsert new_emp2.xml

testDeleteRowプログラムに同じupd_emp.xml文書を渡して、従業員7400および7369を削除します。

java testDeleteKey upd_emp.xml

次の単一のDELETE文が生成されます。

DELETE FROM hr.employees WHERE employee_id=?;

次のDELETE文が、それぞれ各従業員に対して実行されます。

DELETE FROM hr.employees WHERE employee_id = 7400;
DELETE FROM hr.employees WHERE employee_id = 7369;

13.3.9 XSUのJava例外の処理

XSUは、処理中に発生したすべての例外を捕捉し、一般的なランタイム例外であるoracle.xml.sql.OracleXMLSQLExceptionをスローします。適切なアクションを実行できる場合は、起動プログラムはこの例外を捕捉する必要はありません。例外クラスには、エラー・メッセージおよび存在する場合は親である例外を取得するためのメソッドがあります。

トピック:

13.3.9.1 親である例外の取得

testException.javaデモ・プログラムは、ランタイム例外をスローし、Exception.getParentException()を起動して親である例外を取得します。

このプログラムを実行すると、次のエラー・メッセージが生成されます。

Caught SQL Exception:ORA-00904: "SD": invalid identifier
13.3.9.2 該当する行がない場合の例外の生成

XSUは、処理する行がない場合はNULL文字列を戻します。ただし、プログラムが例外ハンドラを使用してこの例外を処理できるように、行がなくなるたびに例外をスローできます。

OracleXMLQuery.setRaiseNoRowsException()を起動すると、XSUは、出力用に生成する行がなくなるたびに、oracle.xml.sql.OracleXMLSQLNoRowsExceptionを発生させます。これはランタイムの例外であり、捕捉する必要はありません。

noRowsTest.javaデモ・プログラムは、pageTest.javaに定義されたpageTestクラスをインスタンス化します。終了を確認する条件が、結果がnullかどうかの確認から、例外ハンドラに変更されました。

noRowsTest.javaプログラムは、pageTestオブジェクトを作成し、SQL問合せを使用して初期化します。プログラムは次のように続行します。

  1. 問合せオブジェクトを構成するか、行がなくなった場合の例外を発生させます。次のコード部分は、この方法を示します。
    pageTest test = new pageTest("SELECT * from employees");
    ...
    test.qry.setRaiseNoRowsException(true);
    
  2. 結果セット内を無限ループして、一度に10行ずつ取得します。使用可能な行がなくなると、プログラムは例外を発生させます。次のコード部分は、一度に10行ずつ結果セットをスクロールするpageTest.nextPage()を起動します。
    try
    {
      while(true)
        System.out.println(test.nextPage());
    }
    
  3. 行がなくなったときの例外を捕捉し、"END OF OUTPUT"と出力します。次のコード部分は、この方法を示します。
    catch(oracle.xml.sql.OracleXMLSQLNoRowsException e)
    {
      System.out.println(" END OF OUTPUT "); 
      try
      {
        test.close();
      }
      catch ( Exception ae )
      {
        ae.printStackTrace(System.out);
      }
    }
    

プログラムをコンパイルした後、次のようにコマンドラインから実行します。

java noRowsTest

13.4 XSU PL/SQL APIを使用したプログラミング

このトピックでは、XSU PL/SQL APIを利用するプログラミング・タスクについて説明します。

注意:

パフォーマンス向上のため、DBMS_XMLQueryおよびDBMS_XMLSaveのかわりに、DBMS_XMLGenおよびDBMS_XMLStoreの使用を検討してください。前者の2つのパッケージはCで記述され、データベース・カーネルに組み込まれています。XMLElementなどのSQL/XML関数を使用して、データベースのXMLにアクセスすることもできます。

トピック:

13.4.1 DBMS_XMLQueryを使用した単純な問合せからのXMLの生成

パッケージDBMS_XMLQueryを使用してSQL問合せからXMLデータを生成する方法を示します。

この例を実行するには、hrとしてデータベースに接続し、printClobOut.sqlスクリプトを実行します。このスクリプトは、CLOBを出力バッファに出力する単純なプロシージャprintClobOutを作成します。SQL*PlusでprintClobOutプロシージャを実行すると、入力CLOBが画面に出力されます。結果を表示するには、サーバーの出力をONに設定します。表示バッファを増やして全出力を表示する必要がある場合があります。

simpleQuery.sqlスクリプトを実行して、hr.employees表から20行選択し、XML文書をCLOBとして取得します。プログラムは、最初に問合せを渡してコンテキスト・ハンドルを取得し、次にgetXMLファンクションを起動してCLOB値を取得します。文書のエンコーディングは、データベース・キャラクタ・セットのエンコーディングと同じになります。このサンプル・アプリケーションでは、printClobOut.sqlを実行してprintClobOutプロシージャが作成されていることが前提になっています。

13.4.2 DBMS_XMLQueryを使用した要素名の指定

XSUのPL/SQL APIを使用して、デフォルトのROWおよびROWSET要素名を変更できます。これらはデフォルトの名前であり、結果の各行の先頭と末尾、および出力XML文書全体の先頭と末尾にそれぞれ置かれます。このタスクを実行するには、PL/SQLプロシージャsetRowTagNameおよびsetRowSetTagNameを使用します。

hrとして接続し、SQL*PlusでchangeElementName.sqlスクリプトを実行して、employees表の最初の20行をXML文書として取得します。無名のPL/SQLブロックによって、ROWおよびROWSET要素名がEMPおよびEMPSETに変更されます。このブロックは、printClobOut.sqlの実行によって作成されたprintClobOutプロシージャを起動します。

生成されるXML文書には、<EMPSET>文書要素が含まれます。各行は、<EMP>タグによって区切られています。

13.4.3 DBMS_XMLQUERYを使用した結果ページの区切り

PL/SQLパッケージDBMS_XMLQUERYのファンクションを起動することにより、問合せ結果をページ区切りできます。

  • ファンクションsetMaxRowsは、XMLに変換する行の最大数を設定します。この最大値は、前回の結果が生成された、現在の行の位置に関連します。

  • ファンクションsetSkipRowsは、行の値をXMLに変換する前にスキップする行数を指定します。

paginateResult.sqlスクリプトを実行して、結果ページを区切る無名ブロックを実行します。最初の10行のバッチでskipRowsを3に設定し、残りのバッチで0に設定すると、employees表の最初の3行をスキップし、残りの行を一度に10行ずつ出力します。複数のフェッチの場合は、フェッチする行がなくなったときを確認する必要があります。これを行うには、setRaiseNoRowsExceptionを起動します。このプロシージャは、CLOBへの行の書込みがなかった場合に例外を発生させます。この例外は、終了条件として捕捉および使用できます。

13.4.4 XSUへのスタイルシートの設定

XSUのPL/SQL APIを使用して、生成したXML文書にスタイルシートを設定できます。

  • プロシージャsetStylesheetHeaderを使用して、結果にスタイルシート・ヘッダーを設定します。このプロシージャは、XML処理命令を追加して、スタイルシートを含めます。

  • 生成の前に、結果のXML文書にスタイルシートを適用します。このメソッドを使用すると、XML文書をCLOBとして生成してから再度パーサーに送信し、スタイルシートを適用する必要がなくなるため、パフォーマンスが大幅に向上します。XSUはDOM文書を生成し、パーサーを起動し、スタイルシートを適用してから結果を生成します。結果のXML文書にスタイルシートを適用するには、スタイルシートを使用して結果を生成するプロシージャであるsetXSLTを使用します。

13.4.5 XSUでの値のバインド

XSUのPL/SQL APIにより、SQL文に値をバインドできます。文には名前付きバインド変数を指定でき、このバインド変数の前にはコロン(:)を付ける必要があります。

bindSQLVariables.sqlスクリプトは、無名のPL/SQLブロックを実行し、employees表の列にEMPLOYEE_IDおよびFIRST_NAMEの値をバインドします。

13.4.6 XSUを使用したXMLの挿入

表またはビューにXML文書を挿入するには、表名またはビュー名、およびXML文書を指定します。XSUはXML文書(文字列が指定されている場合)を解析し、INSERT文を作成してこの文にすべての値をバインドします。デフォルトでは、XSUは値を表またはビューのすべての列に挿入します。存在しない要素はNULLとして処理されます。

トピック:

13.4.6.1 XSUを使用したすべての列への値の挿入

insProc.sqlデモ・スクリプトを実行して、PL/SQLストアド・プロシージャinsProcを作成します。

このスクリプトは次のパラメータを受け入れます。

  • CLOBとしてのXML文書

  • 文書を挿入する表の名前

insProcプロシージャを起動して、XML文書を表に挿入できます。

insertClob.sqlスクリプトを実行して、xmldocumentという表を作成し、XML文書をCLOBとして表に格納します。XML文書には、従業員7370のLiz Gardnerが記述され、この従業員をhr.employees表に挿入します。

例13-4に示されたinsertEmployee.sqlスクリプトを実行して、insProcストアド・プロシージャをコールし、Liz Gardnerをemployees表に挿入します。

「OracleXMLSaveを使用した行の挿入」に示したように、callinsProcプロシージャを実行すると、例13-5に示す形式のINSERT文が生成されます。

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

例13-3 insertClob.sql

CREATE TABLE hr.xmldocument
  (docid   NUMBER PRIMARY KEY,
  xml_text CLOB);
-- insert an XML document into the CLOB column
INSERT INTO hr.xmldocument (docid,xml_text)
VALUES (1,
       '<?xml version="1.0"?>
       <ROWSET>
        <ROW num="1">
           <EMPLOYEE_ID>7370</EMPLOYEE_ID>
           <FIRST_NAME>Liz</FIRST_NAME>
           <LAST_NAME>Gardner</LAST_NAME>
           <EMAIL>liz.gardner@business.com</EMAIL>
           <PHONE_NUMBER>650-555-6127</PHONE_NUMBER>
           <HIRE_DATE>12/18/2004 0:0:0</HIRE_DATE>
           <SALARY>3000</SALARY>
           <COMMISSION_PCT>0</COMMISSION_PCT>
           <JOB_ID>SH_CLERK</JOB_ID>
           <MANAGER_ID>103</MANAGER_ID>
           <DEPARTMENT_ID>20</DEPARTMENT_ID>
        </ROW>
       </ROWSET>');

例13-4 insertEmployee.sql

DECLARE
  v_xml_text CLOB;
BEGIN
  SELECT xml_text 
    INTO v_xml_text
  FROM hr.xmldocument
  WHERE docid = 1;
  insProc(v_xml_text, 'employees');
END;
/

例13-5 INSERT文の形式

INSERT INTO hr.employees 
  (employee_id, first_name, last_name, email, phone_number, hire_date, 
   salary, commission_pct, manager_id, department_id)
VALUES
  (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);     
13.4.6.2 XSUを使用した一連の列への挿入

挿入処理を行う列名のリストを作成し、それをPL/SQLプロシージャDBMS_XMLSaveに渡すことができます。

「OracleXMLSaveを使用した列のサブセットへのXMLの挿入」で説明しているように、値を挿入する必要のない列がある場合もあります。プロシージャsetUpdateColumnNameを繰り返し起動し、そのたびに更新する列名を渡すことで、これらの値を設定できます。列名の設定は、clearUpdateColumnListを起動すると消去されます。

testInsert.sqlデモ・スクリプトを実行して、testInsertというPL/SQLストアド・プロシージャを作成します。このプロシージャを使用して、CLOB型のXMLデータをhr.employees表に挿入できます。

例13-6insertClob2.sqlスクリプトを実行して、新しい従業員Jordanについて記述されたXML文書をxmldocument表のCLOB列に挿入します。文書に、employees表のすべての列に対応する要素が含まれるわけではありません。

例13-7insertEmployee2.sqlスクリプトを実行すると、従業員Jim Jordanのデータがhr.employees表の列のサブセットに挿入されます。

「OracleXMLSaveを使用した列のサブセットへのXMLの挿入」で説明しているように、testInsertを起動すると、次のINSERT文が生成されます。

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

例13-6 insertClob2.sql

-- insert an XML document into the CLOB column  of the xmldocument table with only 
-- some of the possible elements
INSERT INTO hr.xmldocument (docid, xml_text)
VALUES (2,
       '<?xml version="1.0"?>
       <ROWSET>
        <ROW num="1">
           <EMPLOYEE_ID>7401</EMPLOYEE_ID>
           <LAST_NAME>Jordan</LAST_NAME>
           <EMAIL>jim.jordan@business.com</EMAIL>
           <JOB_ID>SH_CLERK</JOB_ID>
           <HIRE_DATE>12/17/2004 0:0:0</HIRE_DATE>
        </ROW>
       </ROWSET>');

例13-7 insertEmployee2.sql

DECLARE
  v_xml_text CLOB;
BEGIN
  SELECT xml_text 
    INTO v_xml_text
  FROM hr.xmldocument
  WHERE docid = 2;
  testInsert(v_xml_text);
END;
/

13.4.7 XSUを使用した更新

XML文書を使用して、表内の指定したフィールドを更新できます。キーとして使用する列を指定するか、更新する列のリストを渡すことができます。

これについては、「OracleXMLSaveを使用した行の更新」で説明しています。

トピック:

13.4.7.1 PL/SQLを使用したキー列の更新

次のサンプル・スクリプトは、PL/SQLプロシージャを使用してキー列を更新する方法を示しています。

testUpdateKey.sqlスクリプトを実行して、testUpdateKeyというPL/SQLプロシージャを作成します。このプロシージャは、hr.employees表の列employee_idを主キーとして使用します。

例13-8insertClob3.sqlスクリプトを実行して、表xmldocumentCLOB列にXML文書を挿入します。この文書は、従業員7400の新しい給与、および従業員7369の新しい仕事のIDおよびマネージャIDを指定します。

例13-9updateEmployee.sqlスクリプトを実行して、プロシージャtestUpdateKeyにXML文書を渡し、2つのUPDATE文を生成します。

最初のROW要素には、次のUPDATE文が生成されます。

UPDATE hr.employees SET salary = 3250 WHERE employee_id = 7400;

2番目のROW要素には、次の文が生成されます。

UPDATE hr.employees SET job_id = 'SA_REP' AND MANAGER_ID = 145 
  WHERE employee_id = 7369;

例13-8 insertClob3.sql

INSERT INTO hr.xmldocument (docid, xml_text)
VALUES (3,
       '<?xml version="1.0"?>
        <ROWSET>
         <ROW num="1">
            <EMPLOYEE_ID>7400</EMPLOYEE_ID>
            <SALARY>3250</SALARY>
         </ROW>
         <ROW num="2">
            <EMPLOYEE_ID>7369</EMPLOYEE_ID>
            <JOB_ID>SA_REP</JOB_ID>
            <MANAGER_ID>145</MANAGER_ID>
         </ROW>
        </ROWSET>');

例13-9 updateEmployee.sql

DECLARE
  v_xml_text CLOB;
BEGIN
  SELECT xml_text 
    INTO v_xml_text
  FROM hr.xmldocument
  WHERE docid = 3;
  testUpdateKey(v_xml_text);
END;
/
13.4.7.2 XSUを使用した一連の列の更新

更新する列のリストを作成し、それをPL/SQLプロシージャDBMS_XMLSaveに渡すことができます。

これについては、「OracleXMLSaveを使用した列リストの更新」で説明しています。

testUpdateSubset.sqlスクリプトを実行すると、PL/SQLプロシージャtestUpdateSubsetが作成されます。このプロシージャは列employee_idをキーとして使用し、表hr.employeessalaryおよびjob_id列のみを更新します。

insertClob4.sqlスクリプトを実行して、xmldocument表にXML文書を挿入します。文書内の<ROW>要素には、従業員100および206の記述があります。各<ROW>要素には、説明テキストを含む10個のサブ要素があります。

例13-10updateEmployee2.sqlスクリプトを実行して、プロシージャtestUpdateSubsetにXML CLOBを渡し、2つのUPDATE文を生成します。

プロシージャは、従業員100および206に関して、setUpdateColumnプロシージャで指定された列、salaryおよびemailのみを更新します。

例13-10 updateEmployee2.sql

DECLARE
  v_xml_text CLOB;
BEGIN
  SELECT xml_text 
    INTO v_xml_text
  FROM hr.xmldocument
  WHERE docid = 4;
  testUpdateSubset(v_xml_text);
END;
/

13.4.8 XSUを使用した削除

削除する行を決定するためにXSUで使用される、キー列のリストを指定できます。これらの列は、DELETE文のWHERE句で指定されます。

これについては、「XSUを使用した行の削除」で説明しています。

トピック:

13.4.8.1 XSUを使用した行による削除

PL/SQLプロシージャを使用して、表から行を削除できます。

testDeleteRow.sqlスクリプトを実行して、testDeleteRow PL/SQLプロシージャを作成します。プロシージャは、入力XML文書のすべての<ROW>要素に対して、hr.employees表から行を削除します。

例13-7で追加した従業員Jim Jordanを削除する必要があるとします。例13-11deleteEmployeeByRow.sqlスクリプトを実行して、XML文書をCLOBとしてtestDeleteRowストアド・プロシージャに渡します。

前述のtestDeleteRowの起動は、次のDELETE文を生成します。

DELETE FROM hr.employees
  WHERE employee_id = 7401 AND last_name = 'JORDAN'
  AND email = 'jim.jordan@business.com' AND job_id = 'SH_CLERK'
  AND hire_date = '12/17/2004 0:0:0';

プログラムは、XML文書内の各<ROW>要素にあるタグ名に基づいてDELETE文を構成します。

例13-11 行による削除

DECLARE
  v_xml_text CLOB;
BEGIN
  SELECT xml_text 
    INTO v_xml_text
  FROM hr.xmldocument
  WHERE docid = 2;
  testDeleteRow(v_xml_text);
END;
/
13.4.8.2 XSUを使用したキーによる削除

削除の主キーとして使用する列を指定できます。このキーを指定するには、PL/SQLファンクションDBMS_XMLSave.setKeyColumnを使用します。

これについては、「OracleXMLSaveを使用したキーによる削除」で説明しています。

testDeleteKey.sqlを実行して作成されたプロシージャtestDeleteKeyは、入力XML文書の各<ROW>要素に対して表employeesから行を削除します。

例13-4で追加した従業員Liz Gardnerを削除する必要があるとします。例13-12deleteEmployeeByKey.sqlスクリプトを実行して、XML文書をCLOBとしてtestDeleteKeyストアド・プロシージャに渡します。

このプロシージャ・コールで、XSUは次のような単一のDELETE文を生成します。

DELETE FROM hr.employees WHERE employee_id=?

XSUはこの文を入力XML文書のすべてのROW要素に使用します。

例13-12 キーによる削除

DECLARE
  v_xml_text CLOB;
BEGIN
  SELECT xml_text 
    INTO v_xml_text
  FROM hr.xmldocument
  WHERE docid = 1;
  testDeleteKey(v_xml_text);
END;
/

13.4.9 XSUを使用した例外の処理

サンプル・スクリプトは、XSUを使用した例外の処理方法を示しています。

優れたPL/SQLコードは、発生可能な例外を考慮して作成されています。raiseException.sqlの無名PL/SQLブロックは、プロシージャDBMS_XMLQuery.getExceptionContentの起動方法をデモしています。SQL*Plusでスクリプトを実行して、次のエラー・メッセージを出力します。

Exception caught 904 ORA-00904: "Z": invalid identifier

13.4.10 XSUを使用したコンテキスト・ハンドルの再利用

場合によっては、同じコンテキスト・ハンドルを使用して複数の操作を実行できます。

前項で示したDMLの例では、同じコンテキスト・ハンドルを複数の操作のために使用できます。saveコンテキストの作成時に指定した同一の表に対してすべての挿入が行われる場合は、同じコンテキストを使用して複数のINSERTを実行できます。同じコンテキストを使用してDML文を混合することもできます。

testDML.sqlスクリプトは、同じコンテキストおよび設定を使用して、ユーザーの入力に基づいてDMLを実行する方法を示します。この例では、すべてのファンクションの起動で同じコンテキストが使用されるように、PL/SQLパッケージの静的変数を使用してコンテキストを格納します。

スクリプトによって作成されたtestDMLパッケージでは、パッケージ全体(セッション)のためのコンテキストを1回作成し、複数のDML操作でコンテキストを再利用します。

注意:

キー列employee_idが、行を識別する方法として更新と削除の両方に使用されることに注意してください。

スクリプトによって作成された3つのプロシージャのどれをコールしてもemployees表を更新できます。

testDML.insertXML(xmlclob);
testDML.deleteXML(xmlclob);
testDML.updateXML(xmlclob);

各プロシージャ・コールが同じコンテキストを使用することで、これらの操作が頻繁に実行される場合は特にパフォーマンスが向上します。

13.5 XSUを使用したプログラミングのヒントと方法

この項では、XSUを使用したプログラムを作成するためのヒントと方法を示します。

トピック:

13.5.1 XSUによるSQLとXML間のマップ方法

SQLとXMLの間のマッピングについて説明します。

表の基本コンポーネントは列ですが、XML文書の基本コンポーネントは要素と属性です。表はどのようにXML文書にマップされるのでしょうか。たとえば、hr.employees表にlast_nameという列がある場合、この構造はXMLで、last_name属性を持つ<EMPLOYEES>要素、または異なるルート要素内の<LAST_NAME>要素として表現されますが、これはどのような方法で行われるのでしょうか。この項では、これらの疑問に答えるため、SQLからXMLおよびXMLからSQLへのマッピングについて説明します。

トピック:

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

SQLデータからXMLデータへのデフォルト・マッピングについて説明します。

hr.employees表の列のデータをXML文書として表示するには、次のようにコマンドラインでXSUを実行します。

java OracleXML getXML -user "hr/password" -withschema \
  "SELECT employee_id, last_name, hire_date FROM employees"

XSUは、入力された問合せに基づいてXML文書を出力します。ドキュメントのルート要素は<DOCUMENT>です。次にサンプル出力を示します。関連のない行はコメントに置き換えられています。

<?xml version = '1.0'?>
<DOCUMENT xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <!-- children of schema element ... -->
   </xsd:schema>
   <ROWSET xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="#/DOCUMENT/xsd:schema[not(@targetNamespace)]">
      <ROW num="1">
         <EMPLOYEE_ID>100</EMPLOYEE_ID>
         <LAST_NAME>King</LAST_NAME>
         <HIRE_DATE>6/17/1987 0:0:0</HIRE_DATE>
      </ROW>
      <!-- additional rows ... -->
   </ROWSET>
</DOCUMENT>

生成されたXMLでは、SQL問合せによって戻された行は<ROWSET>要素の子です。XML文書には次の機能があります。

  • <ROWSET>要素には、戻された行数に応じて、0個以上の<ROW>子要素があります。問合せによって行が生成されなかった場合、<ROW>要素は含まれません。問合せによって行が1つ生成された場合は、1個の<ROW>要素が含まれます。

  • <ROW>要素には、1つの表の行のデータが含まれます。特に、各<ROW>要素には、SELECT文で指定されたデータベースの列と同一の名前およびコンテンツを持つ子要素が1つ以上あります。

トピック:

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

XSUでは、オブジェクト・リレーショナル・スキーマからXML文書を生成できます。

SQL*PlusでcreateObjRelSchema.sqlスクリプトを実行して、オブジェクト・リレーショナル・スキーマを設定し、データを挿入します。スキーマには、ユーザー定義型を使用する2つの列を持つdept1表があります。

コマンドラインからXSUを起動して、次のようにdept1表の問合せを実行できます。

% java OracleXML getXML -user "hr/password" -withschema "SELECT * FROM dept1"

XSUは、例13-13のXML文書を戻します。このXML文書では、関連のない行はコメントに置き換えられています。

前述の例と同様に、この例は正規のマッピングを示しています。<ROWSET>には<ROW>子要素が含まれ、これらの子要素には、dept1の列に対応した子要素が含まれます。たとえば、<DEPTNAME>要素は、dept1.deptname列に対応しています。スカラー型の列に対応する要素は、列からのデータを含みます。

例13-13 XSUにより生成されたサンプル文書

<?xml version='1.0'?>
<DOCUMENT xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <schema targetNamespace="http://xmlns.oracle.com/xdb/SYSTEM"      
           xmlns="http://www.w3.org/2001/XMLSchema"
           xmlns:SYSTEM="http://xmlns.oracle.com/xdb/SYSTEM">
   <!-- children of schema element ... -->
   </xsd:schema>
   <ROWSET xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="#/DOCUMENT/xsd:schema[not(@targetNamespace)]">
      <ROW num="1">
         <DEPTNO>120</DEPTNO>
         <DEPTNAME>Treasury</DEPTNAME>
         <DEPTADDR>
            <STREET>2004 Charade Rd</STREET>
            <CITY>Seattle</CITY>
            <STATE>WA</STATE>
            <ZIP>98199</ZIP>
         </DEPTADDR>
         <EMPLIST>
            <EMPLIST_ITEM>
               <EMPLOYEE_ID>1</EMPLOYEE_ID>
               <LAST_NAME>Mehta</LAST_NAME>
               <SALARY>6000</SALARY>
               <EMPLOYEE_ADDRESS>
                  <STREET>500 Main Road</STREET>
                  <CITY>Seattle</CITY>
                  <STATE>WA</STATE>
                  <ZIP>98199</ZIP>
               </EMPLOYEE_ADDRESS>
            </EMPLIST_ITEM>
         </EMPLIST>
      </ROW>
   </ROWSET>
</DOCUMENT>
 
13.5.1.1.2 複雑な型の列からXMLへのデフォルト・マッピング

複雑な型の列からXMLデータへのデフォルト・マッピングについて説明します。

複雑な型の列に対応する要素の場合、マッピングはより複雑になります。例13-13で、<DEPTADDR>は、オブジェクト型AddressTypedept1.deptAddr列に対応しています。したがって、<DEPTADDR>は、AddressType型で指定された属性に対応する子要素を含みます。AddressTypeの属性streetは、子XML要素<STREET>に対応し、他の属性も同様にそれぞれの子要素に対応しています。これらのサブ要素は、対応する属性の型が単純か複雑かによって、それ自体がデータやサブ要素を含む場合があります。

13.5.1.1.3 XMLへのコレクションのデフォルト・マッピング

データベースのコレクションからXMLデータへのデフォルト・マッピングについて説明します。

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

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

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

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

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

XMLデータからSQLデータへのデフォルト・マッピングについて説明します。

XMLからSQLへのマッピングは、SQLからXMLへのマッピングの逆の操作です。XSUを使用してXMLからSQLへのマッピングを行う場合は、次の相違点を考慮に入れてください。

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

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

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

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

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

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

  • XSLTを使用してXML文書を変換して、XML文書を変更します。XSLTスタイルシートをXSUに登録すると、マッピングを試行する前に、受信したXMLを自動的に変換できます。

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

    • ROWのかわりに、データベースの行に対応する要素名を使用

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

13.5.1.3 生成されたXMLのカスタマイズ

状況によっては、特定の構造を持つXMLを生成する必要がある場合があります。生成されたXML文書のデフォルトの構造が必要な構造とは異なる場合があるため、このプロセスにはある程度の柔軟性が必要になります。

トピック:

13.5.1.3.1 データベース・スキーマまたはSQL問合せの変更

ソースのカスタマイズは、SQL問合せまたはデータベース・スキーマを変更することによって行います。

最も単純で強力なソースのカスタマイズは次のとおりです。

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

  • 問合せで次のようにします。

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

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

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

      SELECT employee_name AS "@empno",... FROM employees;
      

例13-14customer.xml文書について考えてみます。

データベース表のセットを設計して、このデータを格納する必要があるとします。XMLは複数のレベルを持つネスト構造であるため、前述のXML文書に正規マッピングされるオブジェクト・リレーショナル・データベース・スキーマを使用できます。SQL*PlusでcreateObjRelSchema2.sqlスクリプトを実行して、このようなデータベース・スキーマを作成します。

スクリプトによって作成されるcustomer_tab表に、customer.xml文書のデータをロードできます。次のようにコマンドラインからXSU for Javaを起動します。

java OracleXML putXML -user "hr/password" -fileName customer.xml customer_tab

オブジェクト・リレーショナルでないデータベース・スキーマにcustomer.xmlをロードするには、標準のリレーショナル・スキーマの最上位にオブジェクトのビューを作成します。たとえば、必要な列を含むリレーショナル表を作成し、最上位にカスタマ・オブジェクトを持つカスタマ・ビューを作成できます。例13-15に、createRelSchema.sqlスクリプトを示します。

次のようにデータをcustomer_viewにロードできます。

java OracleXML putXML -user "hr/password" -fileName customer.xml customer_view

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

特定の列または列のグループをXML要素ではなくXML属性にマップするには、列名に別名を作成し、この別名の前にアットマーク(@)を付加します。たとえば、mapColumnToAtt.sqlスクリプトを使用してhr.employees表に問合せを行い、employee_idをXML属性としてレンダリングできます。

次のようにしてコマンドラインからmapColumnToAtt.sqlスクリプトを実行できます。

java OracleXML getXML -user "hr/password" -fileName "mapColumnToAtt.sql"

注意:

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

例13-14 customer.xml

<?xml version = "1.0"?>
<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>

例13-15 createRelSchema.sql

CREATE TABLE hr.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;
13.5.1.3.2 XSUの変更

XSUでは、SQLデータをXMLに変換するために使用する規則を変更できます。

SQLからXMLへのマッピングでは、次のように変更できます。

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

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

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

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

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

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

13.5.2 XSUのSQL文の処理方法

XSUでのSQL文の処理方法について説明します。

トピック:

13.5.2.1 XSUのデータベースへの問合せ方法

XSUはSQL問合せを実行し、データベースからResultSetを取得します。次に、XSUはResultSetに関するメタデータを取得し、分析します。

「SQLからXMLへのデフォルト・マッピング」で説明したマッピングを使用して、XSUはSQLの結果セットを処理し、XML文書に変換します。

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

13.5.2.2 XSUの行の挿入方法

XML文書のコンテンツを表またはビューに挿入するときにXSUで実行される手順について説明します。

XML文書のコンテンツを表またはビューに挿入するとき、XSUは次のことを実行します。

  1. ターゲットの表またはビューに関するメタデータを取得します。

  2. メタデータに基づいて、SQL INSERT文を生成します。たとえば、ターゲット表がdept1で、dept1からXML文書が生成されるとします。XSUによって次のINSERT文が生成されます。

    INSERT INTO dept1 (deptno, deptname, deptaddr, emplist) VALUES (?,?,?,?)
    
  3. XML文書を解析し、各レコードに対して、適切な列または属性に適切な値をバインドします。たとえば、INSERT文に次のような値をバインドします。

    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'),...)
    
  4. 文を実行します。INSERT処理を最適化して、バッチで挿入およびコミットできます。

関連項目:

バッチの詳細は、「OracleXMLSaveを使用した行の挿入」を参照してください

13.5.2.3 XSUの行の更新方法

更新および削除の文は、データベース表内の2つ以上の行に影響するという点で挿入と異なります。

挿入では、表にトリガーまたは制約がない場合は、XML文書の1つの<ROW>要素の影響を受けるのは表内で最大1つの行のみです。更新および削除では、一致する列が表内のキー列でない場合は、XML要素が2つ以上の行と一致する場合があります。

更新の文には、更新する行を識別するためにXSUが必要とするキー列のリストを提供する必要があります。たとえば、次のフラグメントを含むXML文書があるとします。

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

DEPTNAMEの値をSportsからSportsDeptに変更します。DEPTNOをキー列として指定すると、XSUは次のUPDATE文を生成します。

UPDATE dept1 SET deptname = ? WHERE deptno = ?

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

deptno <- 100
deptname <- SportsDept

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

13.5.2.4 XSUの行の削除方法

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

XSUに渡す次のような文書があるとします。

<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は、各ROW要素に対してDELETE文を構築します。

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

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

deptno   <- 100
deptname <- sports
deptaddr <- addresstype('100 redwood shores pkwy','redwood city','ca',
            '94065')
13.5.2.5 DML実行後のXSUのコミット方法

デフォルトでは、XSUは明示的なコミットを行いません。AUTOCOMMITが、JDBC接続のデフォルトであるオンになっている場合、文の各バッチを実行した後、XSUはCOMMITを実行します。

AUTOCOMMITをオフにし、setCommitBatchを使用して、XSUがコミットする前に実行する文の数を指定することで、この動作をオーバーライドできます。エラーが発生した場合、XSUは、XSUへのコール前のターゲット表の状態、またはXSUへの現在のコール中に行われた前回のコミット後の状態にロールバックします。