ヘッダーをスキップ
Oracle® XML DB開発者ガイド
11gリリース2 (11.2)
B70200-03
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

3 Oracle XML DBの使用

この章では、Oracle XML DBの使用方法について概説します。この章の例では、発注書のXMLコンテンツへのアクセスおよび管理の方法を示します。発注書は高度に構造化された文書ですが、ほとんど構造化されていないXML文書に対しても、ここに示す方法を使用することができます。

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

XMLデータをXMLTypeとして格納

Oracle XML DBが導入される前は、次の2つの方法でXMLコンテンツをOracle Databaseに格納していました。

  • Oracle XML Developer's Kit(XDK)を使用してXML文書をOracle Database外部で解析し、抽出したXMLデータをデータベース内の1つ以上の表に行として格納します。

  • キャラクタ・ラージ・オブジェクト(CLOB)、バイナリ・ラージ・オブジェクト(BLOB)、バイナリ・ファイル(BFILE)またはVARCHAR列を使用して、XML文書をOracle Databaseに格納します。

いずれの場合も、Oracle DatabaseはXMLコンテンツを管理していることを認識しません。

Oracle XML DBおよびXMLType抽象データ型により、Oracle DatabaseはXML対応になります。XMLデータをXMLType列または表として格納すると、Oracle Databaseはコンテンツに対してXML固有の操作を実行できます。たとえば、XMLの検証や最適化の操作などです。XMLType記憶域では、データベース内のXMLコンテンツを非常に効率的に処理できます。

XMLTypeの概要

XMLTypeは、データベースのXMLデータのネイティブな処理に対応した抽象データ型です。

  • XMLTypeには、データベースのXMLデータの作成、抽出および索引付けを行う組込みメソッドが含まれています。

  • XMLTypeは、XMLデータへのSQLアクセスを提供します。

  • XMLTypeの機能は、PL/SQLおよびJavaで提供される一連のApplication Program Interface(API)を介して使用することもできます。XMLTypeは、PL/SQLストアド・プロシージャのパラメータ、戻り値および変数に使用できます。

XMLTypeを使用すると、SQL開発者は、XMLでの作業中にリレーショナル・データベースの機能を使用できます。XML開発者は、リレーショナル・データベースでの作業中にXML標準の機能を使用できます。

XMLTypeは、表の列およびビューのデータ型として使用できます。XMLType変数は、PL/SQLストアド・プロシージャのパラメータおよび戻り値として使用できます。また、XMLTypeは、SQL、PL/SQL、C、Java(JDBCを介して)およびOracle Data Provider for .NET(ODP.NET)でも使用できます。

XMLType APIによって、XMLコンテンツを操作する有効なメソッドがいくつか提供されています。たとえば、メソッドextract()は、XMLTypeインスタンスから1つ以上のノードを抽出します。

Oracle XML DBの機能は、関連するXML標準(XML Parser、XML DOM、XML Schema Validatorなど)のOracle XML Developer's KitのC実装に基づいています。


関連項目:


XMLTypeデータ型およびAPIのメリット

XMLTypeデータ型およびApplication Program Interface(API)は、XMLコンテンツに対するSQL操作およびSQLコンテンツに対するXML操作を可能にします。

  • 汎用API: XMLTypeには、組込み関数、索引付けおよびナビゲーション・サポートが含まれるアプリケーション開発用の汎用APIが備わっています。

  • XMLTypeおよびSQL: XMLTypeは、SQL文で他のデータ型と組み合せて使用できます。たとえば、XMLType列を問い合せ、抽出の結果をリレーショナル列と結合できます。Oracle Databaseでは、このような問合せを実行するための最適な方法を判断します。

  • 索引付け: 複数の種類の索引を作成して、XMLデータに対する問合せのパフォーマンスを向上できます。

    • XMLTypeデータの構造化記憶域の場合は、XMLType表および列の基礎となるBツリー索引およびファンクション索引をオブジェクト・リレーショナル表に作成できます。ファンクション索引は、スカラー・データ(単一の要素または属性を表す列)のみに作成します。

    • XMLTypeデータの非構造化およびバイナリXML記憶域の場合は、XMLIndex索引を作成できます。これは、ドキュメントのXML構造を対象とした索引です。

    • XMLデータのテキスト・コンテンツの索引は、Oracle TextのCONTEXT索引を使用して作成でき、全文検索で使用できます。これはすべてのXMLType記憶域モデルに適用されます。

XMLType表および列の作成

XMLTypeは抽象データ型なので、XMLType表または列を容易に作成することができます。記憶域オプションとXML Schemaを指定しない基本的なCREATE TABLE文では、XMLTypeデータはバイナリXMLとして格納されます。脚注 1 

例3-1ではXMLType列を作成し、例3-2ではXMLType表を作成します。

例3-1 XMLType列を含む表の作成

CREATE TABLE mytable1 (key_column VARCHAR2(10) PRIMARY KEY, xml_column XMLType);

例3-2 XMLType表の作成

CREATE TABLE mytable2 OF XMLType;

注意:

各自のデータベース・スキーマと異なるデータベース・スキーマにXMLType表を作成するには、権限CREATE ANY TABLEだけでなく、権限CREATE ANY INDEXも必要です。これは、表の作成時に列OBJECT_IDに一意索引が作成されるためです。列OBJECT_IDには、システム生成のオブジェクト識別子が格納されます。

仮想列を使用したバイナリXMLデータのパーティション化または制約

XMLデータには独自の構造がありますが、XMLTypeのオブジェクト・リレーショナル記憶域を除き、データベースのデータ構造には直接反映されません。つまり、個別のXML要素および属性がデータベースの個別の列や表にマップされることはありません。

したがって、個別の要素や属性の値に応じてXMLデータを制約またはパーティション化する場合、リレーショナル・データの標準的な手法は適用できません。このため、対象のXMLデータを表す仮想列を作成してから、その仮想列を使用して必要な制約またはパーティションを定義する必要があります。

この方法は、バイナリXMLとして格納されているXMLデータにのみ適用されます。非構造化記憶域を使用するXMLデータの場合、データベースはXML構造を認識せず、データはフラット・テキストとして扱われますが、バイナリXML記憶域の場合、構造が認識されます。この構造についての情報を使用して仮想列を作成すると、データベースではそれを制約またはパーティションに使用できます。

手順は次のとおりです。

  1. 対象のXMLデータに対応する仮想列を定義します。

  2. その列を使用して、XMLTypeデータを一括してパーティション化または制約します。

XMLTypeデータに対する仮想列の作成は、他の型のデータを使用した仮想列の作成と同様ですが、構文が多少異なります。特に、列定義に関連付けて制約を指定することができません。

XMLTypeは抽象データ型なので、仮想列をXMLType表に作成する場合、それらの列は非表示になります。これらはDESCRIBE文などに表示されません。表示されないことで、DESCRIBEなどの操作を使用するツールが、仮想列に惑わされずに正常に機能することができます。


注意:

  • バイナリXML表のパーティショニングは11gリリース2 (11.2)以降でサポートされています。データベースの互換性(ファイルinit.ora内のパラメータcompatible)が11.2以上の場合にのみサポートされます。

  • レンジ、ハッシュおよびリストのパーティション化がサポートされています。

  • 仮想列を使用すると、XMLTypeをパーティション化できます。XMLデータの仮想列を定義する列を使用して、XMLType を含むリレーショナル表をパーティション化することはできません。


XML要素または属性に基づく仮想列を作成するには、その要素や属性を含むSQL式によって仮想列を定義します。したがって、作成される列はファンクション・ベースです。これには、例3-3に示すように、SQL/XML関数XMLCastおよびXMLQueryを使用します。関数XMLQueryのXQuery式引数は、子および属性の軸のみを使用する簡単なXPath式にする必要があります。

例3-3 仮想列を使用したバイナリXML表のパーティション化

CREATE TABLE po_binaryxml OF XMLType
  XMLTYPE STORE AS BINARY XML
  VIRTUAL COLUMNS
    (DATE_COL AS (XMLCast(XMLQuery('/PurchaseOrder/@orderDate'
                                   PASSING OBJECT_VALUE RETURNING CONTENT)
                          AS DATE)))
  PARTITION BY RANGE (DATE_COL)
    (PARTITION orders2001 VALUES LESS THAN (to_date('01-JAN-2002')),
     PARTITION orders2002 VALUES LESS THAN (MAXVALUE));

例3-3では、仮想列DATE_COLを使用してXMLType表をパーティション化します。この列は、発注書のorderDate要素をターゲットにしています。

パーティショニング用に仮想列を使用するには、そのデータ型が一定である必要があります。列または表内のXMLTypeデータが混在している場合、XML Schemaを使用してエンコードされる文書もあれば、スキーマを使用せずにエンコードされる文書もあります。このため、仮想列内のすべての行に常に同じデータ型が使用されるように、ファンクション式をキャストする必要があります。


注意:

パフォーマンスを最適にするため、パーティション化キーとして、XML文書の最初の32KB以内にターゲットがあるXPath式を選択してください。

バイナリXMLデータに対する制約も、同様の方法で定義します。例3-20を参照してください。


関連項目:


Oracle XML DBへのXMLコンテンツのロード

XMLコンテンツは、次の方法を使用してOracle XML DBにロードできます。

SQLまたはPL/SQLを使用したXMLコンテンツのロード

SQLまたはPL/SQLの簡単なINSERT操作を使用して、XML文書をデータベースにロードできます。文書は、XMLType列または表として格納する前に、XMLTypeコンストラクタの1つを使用してXMLTypeインスタンスに変換する必要があります。


関連項目:


XMLTypeコンストラクタを使用すると、VARCHARCLOBおよびBFILE値を含む様々なソースからXMLTypeインスタンスを作成できます。このコンストラクタは、XMLTypeの作成に関連する処理量を減らす追加の引数を受け入れます。たとえば、ソースのXML文書が有効だとわかっている場合には、有効かどうかわからない場合に実行される型チェックを無効にする引数をコンストラクタに指定できます。

さらに、ソース・データがデータベース・キャラクタ・セットでエンコードされていない場合、XMLTypeインスタンスはBFILE値またはBLOB値を使用して構成できます。ソース・データのエンコーディングは、コンストラクタのキャラクタ・セットID(csid)引数で指定されます。

例3-5に、XMLコンテンツをXMLType表に挿入する方法を示します。この挿入を行う前に、処理するファイルが含まれたディレクトリを指すデータベース・ディレクトリ・オブジェクトを作成する必要があります。作成するためには、CREATE ANY DIRECTORY権限が必要です。


関連項目:

『Oracle Database SQL言語リファレンス』の第18章のGRANTに関する項

例3-4 データベース・ディレクトリの作成

CREATE DIRECTORY xmldir AS path_to_folder_containing_XML_file;

例3-5 XMLType表へのXMLコンテンツの挿入

INSERT INTO mytable2 VALUES (XMLType(bfilename('XMLDIR', 'purchaseOrder.xml'),
                                     nls_charset_id('AL32UTF8')));

nls_charset_idに渡される値は、読み取られるファイルのエンコーディングがUTF-8であることを示します。

SQL INSERTを使用して、コレクションを含む大規模な文書を(XMLType列ではなく)XMLType表に挿入する場合、Oracle XML DBによってロード時間とメモリー使用量が最適化されます。

Javaを使用したXMLコンテンツのロード

例3-6は、ドキュメント・オブジェクト・モデル(DOM)を指定して最初にJavaでXMLTypeインスタンスを作成することによって、XMLコンテンツをOracle XML DBにロードする方法を示しています。

例3-6 Javaを使用したXMLType表へのコンテンツの挿入

public void doInsert(Connection conn, Document doc)
throws Exception
{
   String SQLTEXT = "INSERT INTO purchaseorder VALUES (?)";
   XMLType xml = null;
   xml = XMLType.createXML(conn,doc);
   OraclePreparedStatement sqlStatement = null;
   sqlStatement = (OraclePreparedStatement) conn.prepareStatement(SQLTEXT);
   sqlStatement.setObject(1,xml);
   sqlStatement.execute();
}

単純なバルク・ローダー・アプリケーションがOracle Technology Network (OTN)サイト(http://www.oracle.com/technetwork/database-features/xmldb/overview/index.html)で入手可能です。これにはJava Database Connectivity (JDBC)を使用してXMLファイルのディレクトリをOracle XML DBにロードする方法が示されています。JDBCは、Oracle Databaseに対する一連のJavaインタフェースです。

Cを使用したXMLコンテンツのロード

例3-7に、DOMを指定してXMLTypeインスタンスを作成することによって、CコードでXMLコンテンツをXMLType表に挿入する方法を示します。

例3-7 Cを使用したXMLType表へのコンテンツの挿入

#include "stdio.h"
#include <xml.h>
#include <stdlib.h>
#include <string.h>
#include <ocixmldb.h>
OCIEnv *envhp;
OCIError *errhp;
OCISvcCtx *svchp;
OCIStmt *stmthp;
OCIServer *srvhp;
OCIDuration dur;
OCISession *sesshp;
oratext *username = "QUINE";
oratext *password = "************";         /* Replace with the real password. */
oratext *filename = "AMCEWEN-20021009123336171PDT.xml";
oratext *schemaloc = "http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd";
 
/*--------------------------------------------------------*/
/* Execute a SQL statement that binds XML data            */
/*--------------------------------------------------------*/
 
sword exec_bind_xml(OCISvcCtx *svchp, OCIError *errhp, OCIStmt *stmthp,
                    void *xml,        OCIType *xmltdo, OraText *sqlstmt)
{
  OCIBind *bndhp1 = (OCIBind *) 0;
  sword  status = 0;
  OCIInd ind = OCI_IND_NOTNULL;
  OCIInd *indp = &ind;
  if(status = OCIStmtPrepare(stmthp, errhp, (OraText *)sqlstmt,
                             (ub4)strlen((const char *)sqlstmt),
                             (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT))
    return OCI_ERROR;
  if(status = OCIBindByPos(stmthp, &bndhp1, errhp, (ub4) 1, (dvoid *) 0,
                           (sb4) 0, SQLT_NTY, (dvoid *) 0, (ub2 *)0,
                           (ub2 *)0, (ub4) 0, (ub4 *) 0, (ub4) OCI_DEFAULT))
    return OCI_ERROR;
  if(status = OCIBindObject(bndhp1, errhp, (CONST OCIType *) xmltdo,
                            (dvoid **) &xml, (ub4 *) 0,
                            (dvoid **) &indp, (ub4 *) 0))
    return OCI_ERROR;
  if(status = OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
                             (CONST OCISnapshot*) 0, (OCISnapshot*) 0,
                             (ub4) OCI_DEFAULT))
    return OCI_ERROR;
  return OCI_SUCCESS;
}
 
/*--------------------------------------------------------*/
/* Initialize OCI handles, and connect                    */
/*--------------------------------------------------------*/
 
sword init_oci_connect()
{
. . .
}
 
/*--------------------------------------------------------*/
/* Free OCI handles, and disconnect                       */
/*--------------------------------------------------------*/
 
void free_oci()
{
. . .
}
 
void main()
{
  OCIType *xmltdo;
  xmldocnode  *doc;
  ocixmldbparam params[1];
  xmlerr       err;
  xmlctx  *xctx;
  oratext *ins_stmt;
  sword    status;
  xmlnode *root;
  oratext buf[10000];
 
  /* Initialize envhp, svchp, errhp, dur, stmthp */
  init_oci_connect();
 
  /* Get an XML context */
  params[0].name_ocixmldbparam = XCTXINIT_OCIDUR;
  params[0].value_ocixmldbparam = &dur;
  xctx = OCIXmlDbInitXmlCtx(envhp, svchp, errhp, params, 1);
  if (!(doc = XmlLoadDom(xctx, &err, "file", filename,
                         "schema_location", schemaloc, NULL)))
    {
      printf("Parse failed.\n");
      return;
    }
  else
    printf("Parse succeeded.\n");
  root = XmlDomGetDocElem(xctx, doc);
  printf("The xml document is :\n");
  XmlSaveDom(xctx, &err, (xmlnode *)doc, "buffer", buf, "buffer_length", 10000, NULL);
  printf("%s\n", buf);
 
  /* Insert the document into my_table */
  ins_stmt = (oratext *)"insert into purchaseorder values (:1)";
  status = OCITypeByName(envhp, errhp, svchp, (const text *) "SYS",
                         (ub4) strlen((const char *)"SYS"), (const text *) "XMLTYPE",
                         (ub4) strlen((const char *)"XMLTYPE"), (CONST text *) 0,
                         (ub4) 0, OCI_DURATION_SESSION, OCI_TYPEGET_HEADER,
                         (OCIType **) &xmltdo);
  if (status == OCI_SUCCESS)
    {
      status = exec_bind_xml(svchp, errhp, stmthp, (void *)doc,
                             xmltdo, ins_stmt);
    }
  if (status == OCI_SUCCESS)
    printf ("Insert successful\n");
  else
    printf ("Insert failed\n");
 
  /* Free XML instances */
  if (doc)
    XmlFreeDocument((xmlctx *)xctx, (xmldocnode *)doc);
  /* Free XML CTX */
  OCIXmlDbFreeXmlCtx(xctx);
  free_oci();
}

注意:

この機能を簡単に説明するために、この例では、デプロイされたシステムで通常使用されるパスワード管理手法を実行していません。本番環境では、Oracle Databaseパスワード管理のガイドラインに従い、サンプル・アカウントをすべて無効化してください。パスワード管理のガイドラインおよびセキュリティに関するその他の推奨事項は、『Oracle Databaseセキュリティ・ガイド』を参照してください。


関連項目:

この例の完全なリストは、付録A「Oracleが提供するXML Schemaおよび例」を参照してください。

小規模なXML文書を含む大規模なXMLファイルのロード

小規模なXML文書のコレクションで構成された大規模なXMLファイルをロードするときは、Simple API for XML(SAX)の解析機能を使用してファイルを一連の小規模な文書に分割してから文書を挿入すると、効率的にロードできます。SAXは、XML Parserがイベント・ベース・アプリケーション用に提供するXML標準インタフェースです。

SAXを使用して、ノードのコレクションから各文書を作成することによって、30MB以上の大規模なXMLファイルからデータベース表をロードできます。XMLファイルは、バルク・ロードすることもできます。


関連項目:


SQL*Loaderを使用した大規模なXMLファイルのロード

大量のXMLデータをOracle Databaseにロードするには、SQL*Loaderを使用します。SQL*Loaderは、従来型パスまたはダイレクト・パスのいずれかのモードでロードを実行します。表3-1に、2つのモードの比較を示します。

表3-1 SQL*Loaderの従来型パスおよびダイレクト・パスによるロード・モード

従来型パスによるロード・モード ダイレクト・パスによるロード・モード

SQLを使用してデータをOracle Databaseにロードします。これはデフォルトのモードです。

SQLをバイパスして、データを直接Oracle Databaseにロードします。

メリット: SQLセマンティクスに従います。たとえば、トリガーが起動され、制約がチェックされます。

メリット: 従来のロード・モードより高速にデータをロードできます。

デメリット: ダイレクト・ロード・モードよりもデータのロードが遅くなります。

デメリット: SQLセマンティクスに従いません。たとえば、トリガーは起動されず、制約もチェックされません。


SQL*Loaderのダイレクト・パス・モードでLOBをロードすると、多くのメモリーを使用できます。メッセージSQL*Loader 700 (out of memory)が表示された場合は、オペレーティング・システムおよびプロセス・メモリーで処理できる行より多くの行が各ロード・コールに含まれている可能性があります。回避策: ROWSオプションを使用して、各データ保存で読み取られる行数を少なくします。

DBMS_XDBを使用したリポジトリへのXML文書のロード

XML文書をOracle XML DBリポジトリに格納して、表ベースではなくパスベースの方法でその文書にアクセスすることも可能です。指定のパスのリポジトリにXML文書をロードするには、PL/SQL関数DBMS_XDB.createResourceを使用します。例3-8に、これを示します。

例3-8 CREATERESOURCEを使用したリポジトリへのXMLコンテンツの挿入

DECLARE
  res BOOLEAN;
BEGIN
  res := DBMS_XDB.createResource('/home/QUINE/purchaseOrder.xml',
                                 bfilename('XMLDIR', 'purchaseOrder.xml'),
                                 nls_charset_id('AL32UTF8'));
END;/

Oracle XML DBを構成して使用するための多くの操作は、1つ以上のXML文書の処理に基づいています。たとえば、XML Schemaの登録や、XSL変換の実行などです。これらのXML文書をOracle Databaseで使用可能にする最も簡単な方法は、そのXML文書をOracle XML DBリポジトリにロードすることです。

プロトコルを使用したリポジトリへの文書のロード

Oracle XML DBリポジトリには、XML Schemaに基づくXML文書もXML Schemaに基づかないXML文書も格納できます。HTMLファイル、画像ファイルおよびMicrosoft Word文書などのXMLデータでないコンテンツも格納できます。

Windows ExplorerなどWebDAVをサポートするツールからWebDAVプロトコルなどのプロトコルを使用して、ローカル・ファイル・システムからOracle XML DBリポジトリにXML文書をロードできます。図3-1に、SCOTTフォルダのコンテンツをローカル・ハード・ドライブからOracle XML DBリポジトリ内のフォルダpoSourceにコピーする簡単なドラッグ・アンド・ドロップ操作を示します。

図3-1 Windows Explorerを使用したリポジトリへのコンテンツのロード

図3-1の説明が続きます
「図3-1 Windows Explorerを使用したリポジトリへのコンテンツのロード」の説明

コピーされたフォルダには、XML Schema文書、HTMLページおよびいくつかのXSLTスタイルシートが含まれていることがあります。

XML文書のキャラクタ・セット

この項では、XML文書のキャラクタ・セットがどのように決定されるかを説明します。


注意:

AL32UTF8は、XMLTypeデータに適したOracle Databaseキャラクタ・セットです。これはIANAの登録済標準であるUTF-8エンコーディングと同等であり、すべての有効なXML文字をサポートします。

Oracle Databaseのデータベース・キャラクタ・セットUTF8(ハイフンなし)とデータベース・キャラクタ・セットAL32UTF8またはキャラクタ・エンコーディングUTF-8を混同しないでください。データベース・キャラクタ・セットUTF8はAL32UTF8で置き換えられています。XMLデータにはUTF8を使用しないでください。キャラクタ・セットUTF8でサポートされるのはUnicodeバージョン3.1以下のみです。すべての有効なXML文字がサポートされるわけではありません。AL32UTF8には、このような制限はありません。

XMLデータにデータベース・キャラクタ・セットUTF8を使用すると、システムが停止したりセキュリティに悪影響を及ぼす可能性があります。入力した文書要素の名前にデータベース・キャラクタ・セットでサポートされない文字が含まれている場合、その文字は置換文字(通常は「?」)で置き換えられます。このため、解析が終了して例外が発生します。リカバリ不能なエラーが発生する場合もあります。


XMLエンコーディング宣言

各XML文書は、エンティティと呼ばれる単位で構成されます。XML文書内の各エンティティでは、異なるエンコーディングの文字が使用される場合があります。UTF-8またはUTF-16以外のエンコーディングで格納されるエンティティは、使用する文字コードを示すエンコーディング仕様が含まれたXML宣言で始まる必要があります。次に例を示します。

<?xml version='1.0' encoding='EUC-JP' ?>

UTF-16でエンコードされたエンティティは、「XML 1.0 Reference」の付録Fで説明されているバイト・オーダー・マーク(BOM)で始まる必要があります。たとえば、大規模なendianのプラットフォームで、UTF-16データ・ストリームに必要なBOMは#xFEFFです。

エンコーディング宣言およびBOMの両方が存在しない場合、XMLエンティティはUTF-8でエンコードされていると想定されます。ASCIIはUTF-8のサブセットであるため、ASCIIエンティティではエンコーディング宣言は必要ありません。

多くの場合、使用する文字コードの情報は、XMLデータ以外に外部ソースからも取得できます。たとえば、データのエンコーディングは、次に示すように、HTTP(S)リクエストのContent-Typeフィールドのcharsetパラメータから取得できます。

Content-Type: text/xml; charset=ISO-8859-4

XML文書をデータベースにロードするときのキャラクタ・セットの決定

Oracle Database 10gリリース1以前のリリースでは、すべてのXML文書は、文書のエンコーディング宣言にかかわらずデータベース・キャラクタ・セットであるとみなされていました。Oracle Database 10gリリース1以降では、文書がデータベースにロードされるときに、その文書のエンコーディングがエンコーディング宣言から検出されます。

ただし、XMLデータがCLOBまたはVARCHAR値から取得される場合、これらの2つのデータ型は常にデータベース・キャラクタ・セットでエンコードされるので、エンコーディング宣言は無視されます。

さらに、プログラムAPIまたは転送プロトコルのいずれかを介してデータをOracle XML DBにロードするときは、外部エンコーディングを指定して文書のエンコーディング宣言をオーバーライドできます。XML Schemaに基づくXML文書に指定のエンコーディングに対して不適切な文字が含まれている場合、その文書をロードしようとするとエラーが発生します。

次の各例で、外部エンコーディングを指定するいくつかの方法を示します。

  • PL/SQL関数DBMS_XDB.createResourceを使用してBFILEからファイル・リソースを作成する場合、CSID引数でファイルのエンコーディングを指定できます。CSIDにゼロを指定すると、ファイルのエンコーディングは文書のエンコーディング宣言から自動検出されます。

    CREATE DIRECTORY xmldir AS '/private/xmldir';
    CREATE OR REPLACE PROCEDURE loadXML(filename VARCHAR2, file_csid NUMBER) IS
      xbfile  BFILE;
      RET     BOOLEAN;
    BEGIN
      xbfile := bfilename('XMLDIR', filename);
      ret := DBMS_XDB.createResource('/public/mypurchaseorder.xml', 
                                     xbfile,
                                     file_csid);
    END;/
    
  • FTPプロトコルを使用して、文書をOracle XML DBにロードします。quote set_charset FTPコマンドを使用して、ロードするファイルのエンコーディングを指定します。

    ftp> quote set_charset Shift_JIS  
    ftp> put mypurchaseorder.xml
    
  • HTTP(S)プロトコルを使用して、文書をOracle XML DBにロードします。Oracle XML DBに転送するデータのエンコーディングは、リクエスト・ヘッダー内に指定します。

    Content-Type: text/xml; charset= EUC-JP
    

データベースからXML文書を取り出すときのキャラクタ・セットの決定

Oracle XML DBに格納されたXML文書は、SQLクライアント、プログラムAPIまたは転送プロトコルを使用して取り出すことができます。取り出すデータのエンコーディングを指定できます(ただし、Oracle Database 10gより前のリリースでは、XMLデータはデータベース・キャラクタ・セットでのみ取り出されるため、エンコーディングを指定できません)。

XMLデータをCLOBまたはVARCHAR2値として格納すると、エンコーディング宣言がある場合、その宣言は、格納と同様に取出しでも常に無視されます。したがって、取り出す文書のエンコーディングは、その文書で明示的に宣言されているエンコーディングとは異なる場合があります。

データベースから取り出されるXML文書のキャラクタ・セットは、次の方法で決定されます。

  • SQLクライアント: XMLの取出しに(SQL*Plusなどの)SQLクライアントが使用される場合、キャラクタ・セットはクライアント側の環境変数NLS_LANGによって決定されます。特に、XMLデータ自体にキャラクタ・セットが明示的に宣言されていても、この設定のほうが優先されます。

    たとえば、クライアント側のNLS_LANG変数をAMERICAN_AMERICA.AL32UTF8に設定し、宣言<?xml version="1.0" encoding="EUC-JP"?>で指定されたエンコーディングEUC_JPのXML文書を取得する場合、取得される文書のキャラクタ・セットはEUC_JPではなくAL32UTF8となります。


    関連項目:

    NLS_LANGの詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。

  • PL/SQLおよびAPI: PL/SQLまたはプログラムAPIを使用すると、XMLデータをVARCHARCLOBまたはXMLTypeデータ型で取り出すことができます。SQLクライアントの場合、NLS_LANGを設定することにより、取り出すデータのエンコーディングを制御できます。

    また、XMLTypeおよびURITypeメソッドを使用して、XMLデータをBLOB値で取り出すこともできます。これにより、BLOB値のキャラクタ・セットを指定できます。次に例を示します。

    CREATE OR REPLACE FUNCTION getXML(pathname VARCHAR2, charset VARCHAR2) 
      RETURN BLOB IS
      xblob BLOB;
    BEGIN
      SELECT XMLSERIALIZE(DOCUMENT e.RES AS BLOB ENCODING charset) INTO xblob
        FROM RESOURCE_VIEW e WHERE equals_path(e.RES, pathname) = 1;
      RETURN xblob;
    END;
    /
    
  • FTP: FTP quote set_nls_localeコマンドを使用して、キャラクタ・セットを設定できます。

    ftp> quote set_nls_locale EUC-JP
    ftp> get mypurchaseorder.xml
    

    関連項目:

    FTP Quoteメソッド

  • HTTP(S): HTTP(S)リクエストでAccept-Charsetパラメータを使用できます。

    /httptest/mypurchaseorder.xml  1.1 HTTP/Host: localhost:2345
    Accept: text/*
    Accept-Charset:  iso-8859-1, utf-8
    

W3CのXML Schema勧告の概要

W3CのXML Schema勧告では、一連のXML文書の構造、コンテンツおよび特定のセマンティクスを指定するための標準化された言語が定義されています。XML Schemaは、XML文書のクラスを示すメタデータとみなすことができます。XML Schemaの勧告については、http://www.w3.org/TR/xmlschema-0/を参照してください。

XMLインスタンス・ドキュメント

指定のXML Schemaに準拠する文書は、そのXML Schemaで定義されたクラスのメンバーまたはインスタンスとみなすことができます。したがって、インスタンス・ドキュメントという用語は、多くの場合、指定したXML Schemaに準拠するXML文書を示すために使用しています。XML Schemaの最も一般的な用途は、指定されたインスタンス・ドキュメントがXML Schemaで定義されたルールに準拠していることを確認することです。

XML Schema for Schemas

W3CのSchemaワーキング・グループは「Schema for Schemas」と呼ばれるXML Schemaを公開しています。このXML Schemaによって、XML Schema言語の定義またはボキャブラリが提供されます。有効なすべてのXML Schemaは、そのXML Schemaで定義されたクラスのメンバーとみなすことができます。したがって、XML Schemaは(http://www.w3.org/2001/XMLSchemaで公開されている)XML Schemaで定義されたクラスに準拠するXML文書です。

XML Schemaの編集

XML Schemaは、次のいずれかを使用して作成および編集できます。

  • emacsやviなどの簡単なテキスト・エディタ

  • Oracle JDeveloperに付属のXMLエディタなど、XML Schemaを認識するエディタ

  • Altova社のXMLSpyなどの明示的なXML Schema作成ツール

XML Schemaの機能

XML Schema言語は、47のスカラー・データ型を定義します。これによって、要素と属性の厳密な型指定が可能になります。W3CのXML Schema勧告では、継承や拡張などのオブジェクト指向の技法もサポートしているため、XML Schema言語で定義された基本データ型から複合的なオブジェクトを持つXML Schemaを設計できます。ボキャブラリには、定義および順序付けの構造体、デフォルト値、必須コンテンツ、ネスト、セットの繰返しおよび再定義が含まれます。Oracle XML DBは、再定義を除くすべての構造体をサポートします。

発注書XML Schemaのテキスト表現

例3-9に、XMLファイルpurchaseOrder.xsdとしての発注書XML Schemaを示します。

例3-9 発注書XML Schema、purchaseOrder.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
  <xs:element name="PurchaseOrder" type="PurchaseOrderType"/>
  <xs:complexType name="PurchaseOrderType">
    <xs:sequence>
      <xs:element name="Reference" type="ReferenceType"/>
      <xs:element name="Actions" type="ActionsType"/>
      <xs:element name="Reject" type="RejectionType" minOccurs="0"/>
      <xs:element name="Requestor" type="RequestorType"/>
      <xs:element name="User" type="UserType"/>
      <xs:element name="CostCenter" type="CostCenterType"/>
      <xs:element name="ShippingInstructions" type="ShippingInstructionsType"/>
      <xs:element name="SpecialInstructions" type="SpecialInstructionsType"/>
      <xs:element name="LineItems" type="LineItemsType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="LineItemsType">
    <xs:sequence>
      <xs:element name="LineItem" type="LineItemType" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="LineItemType">
    <xs:sequence>
      <xs:element name="Description" type="DescriptionType"/>
      <xs:element name="Part" type="PartType"/>
    </xs:sequence>
    <xs:attribute name="ItemNumber" type="xs:integer"/>
  </xs:complexType>
  <xs:complexType name="PartType">
    <xs:attribute name="Id">
      <xs:simpleType>
        <xs:restriction base="xs:string">
          <xs:minLength value="10"/>
          <xs:maxLength value="14"/>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
    <xs:attribute name="Quantity" type="moneyType"/>
    <xs:attribute name="UnitPrice" type="quantityType"/>
  </xs:complexType>
  <xs:simpleType name="ReferenceType">
    <xs:restriction base="xs:string">
      <xs:minLength value="18"/>
      <xs:maxLength value="30"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:complexType name="ActionsType">
    <xs:sequence>
      <xs:element name="Action" maxOccurs="4">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="User" type="UserType"/>
            <xs:element name="Date" type="DateType" minOccurs="0"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="RejectionType">
    <xs:all>
      <xs:element name="User" type="UserType" minOccurs="0"/>
      <xs:element name="Date" type="DateType" minOccurs="0"/>
      <xs:element name="Comments" type="CommentsType" minOccurs="0"/>
    </xs:all>
  </xs:complexType>
  <xs:complexType name="ShippingInstructionsType">
    <xs:sequence>
      <xs:element name="name" type="NameType" minOccurs="0"/>
      <xs:element name="address" type="AddressType" minOccurs="0"/>
      <xs:element name="telephone" type="TelephoneType" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="moneyType">
    <xs:restriction base="xs:decimal">
      <xs:fractionDigits value="2"/>
      <xs:totalDigits value="12"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="quantityType">
    <xs:restriction base="xs:decimal">
      <xs:fractionDigits value="4"/>
      <xs:totalDigits value="8"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="UserType">
    <xs:restriction base="xs:string">
      <xs:minLength value="0"/>
      <xs:maxLength value="10"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="RequestorType">
    <xs:restriction base="xs:string">
      <xs:minLength value="0"/>
      <xs:maxLength value="128"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="CostCenterType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="4"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="VendorType">
    <xs:restriction base="xs:string">
      <xs:minLength value="0"/>
      <xs:maxLength value="20"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="PurchaseOrderNumberType">
    <xs:restriction base="xs:integer"/>
  </xs:simpleType>
  <xs:simpleType name="SpecialInstructionsType">
    <xs:restriction base="xs:string">
      <xs:minLength value="0"/>
      <xs:maxLength value="2048"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="NameType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="20"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="AddressType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="256"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="TelephoneType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="24"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="DateType">
    <xs:restriction base="xs:date"/>
  </xs:simpleType>
  <xs:simpleType name="CommentsType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="2048"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="DescriptionType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="256"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema> 

発注書XML Schemaのグラフィカル表現

図3-2に、XMLSpyを使用して表示した発注書XML Schemaを示します。XMLSpyは、Altova社のグラフィカルでわかりやすいツールで、XML SchemaおよびXML文書を作成および編集するために使用します。詳細は、http://www.altova.comを参照してください。XMLSpyは、WebDAVおよびFTPプロトコルもサポートしているため、Oracle XML DBリポジトリに格納されているコンテンツに直接アクセスして編集できます。

図3-2 XML Schema PurchaseOrderのXMLSpyによるグラフィカル表現

図3-2の説明が続きます
「図3-2 XML Schema PurchaseOrderのXMLSpyによるグラフィカル表現」の説明

この発注書XML Schemaは、次のような一般的なXML文書の主要な機能を示しています。

  • グローバル要素PurchaseOrderは、complexType PurchaseOrderTypeのインスタンスです。

  • PurchaseOrderTypeでは、PurchaseOrder要素を構成する一連のノードが定義されます。

  • LineItem要素は、LineItems要素のコレクションで構成されます。

  • LineItem要素は、2つの要素(DescriptionおよびPart)で構成されます。

  • Part要素には、属性IdQuantityおよびUnitPriceがあります。

Oracle XML DBでのXML Schemaの使用

この項では、Oracle XML DBでのXML Schemaの使用について説明します。

XML SchemaをOracle XML DBとともに使用する理由

次に、XML SchemaをOracle XML DBとともに使用する主な理由を説明します。

XML Schemaを使用したインスタンス・ドキュメントの検証

XML Schemaの最も一般的な用途は、インスタンス・ドキュメントが指定のXML Schemaに準拠していることを確認するメカニズムとして使用することです。XMLTypeメソッドisSchemaValid()およびschemaValidate()によって、XMLTypeとして格納されたインスタンス・ドキュメントのコンテンツを検証します。

ビジネス・ルールまたは書式準拠に対するインスタンス・ドキュメントの制約

XML Schemaは、XMLTypeの表または列の作成時に制約としても使用できます。たとえば、XMLTypeは、XML Schemaで定義されたいずれかのグローバル要素に準拠するXML文書の格納用に制限されます。

データベースへのXMLTypeコンテンツの格納方法の定義

Oracle XML DBでは、XML Schemaを、XMLTypeインスタンスのコンテンツをデータベース内に格納する方法を定義するメカニズムとしても使用します。バイナリXML、構造化、非構造化およびハイブリッド(構造化と非構造化の組合せ)のすべての記憶域モデルで、XML Schemaの使用をサポートしています。XMLTypeに使用可能な記憶域モデルの詳細は、「XMLType記憶域モデル」を参照してください。

XML文書の構造化記憶域

XML文書の構造化記憶域には、文書のコンテンツが一連のSQLオブジェクトに分解されて格納されます。これらのSQLオブジェクトは、SQL 1999タイプのフレームワークに基づいています。XML SchemaがOracle XML DBに登録されると、必要なSQL型定義がXML Schemaから自動的に生成されます。

SQL型定義は、XML Schemaで定義された各complexTypeから生成されます。complexTypeで定義された各要素または属性は、対応するSQL型のSQL属性になります。Oracle XML DBは、XML Schema勧告で定義された47のスカラー・データ型を、SQLでサポートされている19のスカラー・データ型に自動的にマップします。VARRAY型は要素ごとに生成され、複数回、生成される場合があります。

生成されたSQL型により、XML Schemaに準拠するXMLコンテンツは、分解され、情報を損失せずに一連のオブジェクトとしてデータベースに格納できます。文書が収集されると、XML Schemaにより定義された構造体は同等のSQL型に直接マップされます。これにより、Oracle XML DBでは、XMLを管理するときにOracle Databaseのすべての機能を使用でき、文書の格納に必要な容量を大幅に削減できます。また、XMLコンテンツの問合せおよび更新に必要なメモリーの量も削減できます。

ネーミング、マッピングおよび記憶域を制御するためのXML Schemaの注釈付け

W3CのXML Schema勧告では、ベンダー固有の情報をXML Schemaに追加できる注釈メカニズムが定義されています。Oracle XML DBでは、このメカニズムを使用して、XML Schemaとデータベース・オプションの間のマッピングを制御します。

XML Schema注釈を使用すると、次の操作を実行できます。

  • XMLデータを格納するデータベース表の指定

  • XML Schemaデータ型とSQLデータ型(構造化記憶域の場合)の間のデフォルト・マッピングの上書き

  • XMLデータを格納するために作成されるデータベース・オブジェクトおよび属性の命名(構造化記憶域の場合)

オブジェクト・リレーショナルなXMLType記憶域の場合のコレクション格納方法の制御

オブジェクト・リレーショナルに格納されるデータのXML Schemaを登録し、登録パラメータGENTABLESTRUEに設定する場合、関連付けられたXMLインスタンス・ドキュメントを格納するためにデフォルト表が自動的に作成されます。

格納されるときに、XMLコレクション要素の順序は維持されます。結果はOrdered Collectionです。脚注 2 データは次の方法でOrdered Collectionに格納できます。

  • 表内のVARRAY。コレクション内の各要素は、SQLオブジェクトにマップされます。SQLオブジェクトのコレクションは、Ordered Collection Table(OCT)と呼ばれる表に、一連の行として格納されます。デフォルトでは、すべてのコレクションがOCTに格納されます。このデフォルト動作は、XML Schema注釈xdb:storeVarrayAsTable = "true"(デフォルト値)に対応しています。

  • LOB内のVARRAY。コレクション内の各要素は、SQLオブジェクトにマップされます。SQLオブジェクトのコレクション全体が、VARRAYとしてシリアライズされてLOB列に格納されます。指定されたコレクションをLOB内のVARRAYとして格納右するには、XML Schema注釈xdb:storeVarrayAsTable = "false"を使用します。

Ordered Collectionでは表外への格納を使用することもできます。これはXML Schema注釈SQLInline = "false"に対応しており、コレクション表またはLOB内のREFのVARRAYが、表外に格納されたコレクションの内容に追随していることを意味します。

使用する前に、XML Schemaに注釈を付ける必要はありません。XML Schemaに注釈が付いていない場合、Oracle XML DBは一連のデフォルトの前提を使用してXML Schemaを処理します。

この項で取り上げた注釈のいずれも付けなかった場合、Oracle XML DBはコレクションをヒープに基づくOCTとして格納します。OCTを強制的に索引構成表(IOT)として格納するには、DBMS_XMLSCHEMA.registerSchemaOPTIONSパラメータでREGISTER_NT_AS_IOTを渡します。


注意:

OracleからIOTの使用を明示的に指示された場合を除き、IOTでなく、ヒープに基づくOCTを使用してください。IOTの記憶域には、次のような大きな制限があります。
  • コレクション表(IOT)のパーティショニングが無効化されます。

  • 文書レベルのOracle Text索引しかサポートされません。要素に固有の索引や属性に固有の索引は無効になります。

XMLデータでのOracle Textの使用方法の詳細は、第12章「XMLデータの全文検索」を参照してください。



注意:

Oracle Database 11gリリース1より前のリリースの場合:
  • OCTはデフォルトでIOTとして格納されていました。

  • xdb:storeVarrayAsTableのデフォルト値はfalseでした。


Oracle XML DB名前空間の宣言

XML Schemaに注釈を付けるには、最初にOracle XML DB名前空間を宣言する必要があります。Oracle XML DB名前空間は、次のように宣言します。

http://xmlns.oracle.com/xdb

名前空間をXML Schemaで宣言するには、次のような名前空間宣言をXML Schemaのルート要素に追加します。

xmlns:xdb="http://xmlns.oracle.com/xdb"

名前空間接頭辞(xdb)が使用されていることに注意してください。名前空間接頭辞を使用すると、注釈を追加するときに名前空間をxdbに省略できます。

例3-10に、注釈付きのXML Schema PurchaseOrderの最初の部分を示します。完全なXML Schemaのコードは、例A-1を参照してください。

例3-10 注釈付きの発注書XML Schema、purchaseOrder.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:xdb="http://xmlns.oracle.com/xdb"
           version="1.0"
           xdb:storeVarrayAsTable="true">
  <xs:element name="PurchaseOrder" type="PurchaseOrderType" xdb:defaultTable="PURCHASEORDER"/>
  <xs:complexType name="PurchaseOrderType" xdb:SQLType="PURCHASEORDER_T">
    <xs:sequence>
      <xs:element name="Reference" type="ReferenceType" minOccurs="1" xdb:SQLName="REFERENCE"/>
      <xs:element name="Actions" type="ActionsType" xdb:SQLName="ACTIONS"/>
      <xs:element name="Reject" type="RejectionType" minOccurs="0" xdb:SQLName="REJECTION"/>
      <xs:element name="Requestor" type="RequestorType" xdb:SQLName="REQUESTOR"/>
      <xs:element name="User" type="UserType" minOccurs="1" xdb:SQLName="USERID"/>
      <xs:element name="CostCenter" type="CostCenterType" xdb:SQLName="COST_CENTER"/>
      <xs:element name="ShippingInstructions" type="ShippingInstructionsType" 
                  xdb:SQLName="SHIPPING_INSTRUCTIONS"/>
      <xs:element name="SpecialInstructions" type="SpecialInstructionsType" 
                  xdb:SQLName="SPECIAL_INSTRUCTIONS"/>
      <xs:element name="LineItems" type="LineItemsType" xdb:SQLName="LINEITEMS"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="LineItemsType" xdb:SQLType="LINEITEMS_T">
    <xs:sequence>
      <xs:element name="LineItem" type="LineItemType" maxOccurs="unbounded" 
                  xdb:SQLName="LINEITEM" xdb:SQLCollType="LINEITEM_V"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="LineItemType" xdb:SQLType="LINEITEM_T">
    <xs:sequence>
      <xs:element name="Description" type="DescriptionType" 
                  xdb:SQLName="DESCRIPTION"/>
      <xs:element name="Part" type="PartType" xdb:SQLName="PART"/>
    </xs:sequence>
    <xs:attribute name="ItemNumber" type="xs:integer" xdb:SQLName="ITEMNUMBER" 
                  xdb:SQLType="NUMBER"/>
  </xs:complexType>
  <xs:complexType name="PartType" xdb:SQLType="PART_T">
    <xs:attribute name="Id" xdb:SQLName="PART_NUMBER" xdb:SQLType="VARCHAR2">
      <xs:simpleType>
        <xs:restriction base="xs:string">
          <xs:minLength value="10"/>
          <xs:maxLength value="14"/>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
    <xs:attribute name="Quantity" type="moneyType" xdb:SQLName="QUANTITY"/>
    <xs:attribute name="UnitPrice" type="quantityType" xdb:SQLName="UNITPRICE"/>
  </xs:complexType>
  <xs:simpleType name="ReferenceType">
    <xs:restriction base="xs:string">
      <xs:minLength value="18"/>
      <xs:maxLength value="30"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:complexType name="ActionsType" xdb:SQLType="ACTIONS_T">
    <xs:sequence>
      <xs:element name="Action" maxOccurs="4" xdb:SQLName="ACTION" xdb:SQLCollType="ACTION_V">
        <xs:complexType xdb:SQLType="ACTION_T">
          <xs:sequence>
            <xs:element name="User" type="UserType" xdb:SQLName="ACTIONED_BY"/>
            <xs:element name="Date" type="DateType" minOccurs="0" xdb:SQLName="DATE_ACTIONED"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="RejectionType" xdb:SQLType="REJECTION_T">
    <xs:all>
      <xs:element name="User" type="UserType" minOccurs="0" xdb:SQLName="REJECTED_BY"/>
      <xs:element name="Date" type="DateType" minOccurs="0" xdb:SQLName="DATE_REJECTED"/>
      <xs:element name="Comments" type="CommentsType" minOccurs="0" xdb:SQLName="REASON_REJECTED"/>
    </xs:all>
  </xs:complexType>
  <xs:complexType name="ShippingInstructionsType" xdb:SQLType="SHIPPING_INSTRUCTIONS_T">
    <xs:sequence>
      <xs:element name="name" type="NameType" minOccurs="0" xdb:SQLName="SHIP_TO_NAME"/>
      <xs:element name="address" type="AddressType" minOccurs="0" xdb:SQLName="SHIP_TO_ADDRESS"/>
      <xs:element name="telephone" type="TelephoneType" minOccurs="0" xdb:SQLName="SHIP_TO_PHONE"/>
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="moneyType">
    <xs:restriction base="xs:decimal">
      <xs:fractionDigits value="2"/>
      <xs:totalDigits value="12"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="quantityType">
    <xs:restriction base="xs:decimal">
      <xs:fractionDigits value="4"/>
      <xs:totalDigits value="8"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="UserType">
    <xs:restriction base="xs:string">
      <xs:minLength value="0"/>
      <xs:maxLength value="10"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="RequestorType">
    <xs:restriction base="xs:string">
      <xs:minLength value="0"/>
      <xs:maxLength value="128"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="CostCenterType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="4"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="VendorType">
    <xs:restriction base="xs:string">
      <xs:minLength value="0"/>
      <xs:maxLength value="20"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="PurchaseOrderNumberType">
    <xs:restriction base="xs:integer"/>
  </xs:simpleType>
  <xs:simpleType name="SpecialInstructionsType">
    <xs:restriction base="xs:string">
      <xs:minLength value="0"/>
      <xs:maxLength value="2048"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="NameType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="20"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="AddressType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="256"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="TelephoneType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="24"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="DateType">
    <xs:restriction base="xs:date"/>
  </xs:simpleType>
  <xs:simpleType name="CommentsType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="2048"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="DescriptionType">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="256"/>
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

PurchaseOrder XML Schemaには次の2つの名前空間が定義されています。

  • http://www.w3c.org/2001/XMLSchema。これは、W3CによってSchema for Schemasのために予約されています。

  • http://xmlns.oracle.com/xdb。これは、オラクル社によってOracle XML DBのスキーマ注釈用に予約されています。

PurchaseOrderスキーマは、次の注釈を含むいくつかの注釈を使用します。

  • PurchaseOrder要素内のdefaultTable注釈。このXML Schemaに準拠するXML文書をpurchaseorderというデータベース表に格納することを指定します。

  • SQLType注釈。

    SQLTypeが最初に出現したとき、complexType要素PurchaseOrderTypeから生成されたSQL型の名前をpurchaseorder_tと指定します。

    SQLTypeが2番目に出現したとき、complexType要素LineItemTypeから生成されたSQL型の名前をlineitem_tと指定し、LineItem要素のコレクションを管理するSQL型の名前をlineitem_vと指定します。

  • SQLName注釈。purchaseorder_tの各SQL属性の明示的な名前を提供します。

図3-3に、XMLSpyのOracleタブを示します。このタブを使用すると、グラフィカル・エディタでの作業中にOracle XML DBのスキーマ注釈をXML Schemaに容易に追加できます。

図3-3 XMLSpyにおけるOracle XML DBスキーマ注釈のサポート

図3-3の説明が続きます
「図3-3 XMLSpyにおけるOracle XML DB Schema注釈のサポート」の説明

Oracle XML DBへのXML Schemaの登録

XML SchemaをOracle XML DBで使用するには、最初にそのXML SchemaをOracle XML DBに登録する必要があります。XML Schemaを登録した後は、XML文書を検証し、そのXML SchemaにバインドするXMLType表および列を作成できます。

XML SchemaをOracle XML DBに登録するには、次の2つの項目が必要です。

  • XML Schema文書。

  • Oracle Databaseに登録後、XML Schemaの一意の識別子として使用できる文字列。この一意の識別子は、XML Schemaで定義されたクラスのメンバーとしてインスタンス・ドキュメントを識別するために使用されます。通常、識別子はURLの形式を取り、多くの場合、スキーマの場所を示すヒントまたは文書の場所を示すヒントとして参照されます。

XML Schemaを登録するには、PL/SQLプロシージャDBMS_XMLSCHEMA.registerSchemaを使用します。例3-11に、これを示します。デフォルトでは、XML Schemaが登録されると、Oracle XML DBは、インスタンス・ドキュメントの管理に必要なすべてのSQLオブジェクト型とXMLType表を自動的に生成します。XML Schemaは、グローバルまたはローカルとして登録できます。


関連項目:


例3-11 DBMS_XMLSCHEMA.REGISTERSCHEMAを使用したXML Schemaの登録

BEGIN
  DBMS_XMLSCHEMA.registerSchema(
    SCHEMAURL => 'http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd',
    SCHEMADOC => XDBURIType('/source/schemas/poSource/xsd/purchaseOrder.xsd').getCLOB(),
    LOCAL     => TRUE,
    GENTYPES  => TRUE, 
    GENTABLES => TRUE);
END;
/

例3-11では、XML Schemaの一意の識別子は次のとおりです。

http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd

XML Schema文書は、すでにOracle XML DBリポジトリ(/source/schemas/poSource/xsd/purchaseOrder.xsd)にロードされています。

XML Schemaの登録時に、XDBURITypeは、リポジトリ内のXML Schema文書の場所に基づいてXML Schema文書のコンテンツにアクセスします。プロシージャregisterSchemaに渡されるオプションによって、例3-11のスキーマをローカルXML Schemaとして登録する必要があること、SQLオブジェクト、および登録プロセスで表を生成する必要があることが指定されます。

PL/SQLプロシージャDBMS_XMLSCHEMA.registerSchemaは、次の操作を実行します。

  • XML Schemaの解析および検証

  • XML Schemaを記述するOracleデータ・ディクショナリ内の一連のエントリの作成

  • XML Schemaで定義されたcomplexType要素に基づく一連のSQLオブジェクト定義の作成

  • XML Schemaで定義された各グローバル要素のXMLType表の作成

XML Schema登録時のSQL型および表の作成

例3-12では、XML SchemaをOracle XML DBに登録するときに、オブジェクト型を作成します。

例3-12 XML Schemaの登録時のオブジェクトの作成

DESCRIBE purchaseorder_t
 purchaseorder_t is NOT FINAL
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 SYS_XDBPD$                                         XDB.XDB$RAW_LIST_T
 REFERENCE                                          VARCHAR2(30 CHAR)
 ACTIONS                                            ACTIONS_T
 REJECTION                                          REJECTION_T
 REQUESTOR                                          VARCHAR2(128 CHAR)
 USERID                                             VARCHAR2(10 CHAR)
 COST_CENTER                                        VARCHAR2(4 CHAR)
 SHIPPING_INSTRUCTIONS                              SHIPPING_INSTRUCTIONS_T
 SPECIAL_INSTRUCTIONS                               VARCHAR2(2048 CHAR)
 LINEITEMS                                          LINEITEMS_T
 
DESCRIBE lineitems_t
 lineitems_t is NOT FINAL
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 SYS_XDBPD$                                         XDB.XDB$RAW_LIST_T
 LINEITEM                                           LINEITEM_V
 
DESCRIBE lineitem_v
 lineitem_v VARRAY(2147483647) OF LINEITEM_T
 LINEITEM_T is NOT FINAL
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 SYS_XDBPD$                                         XDB.XDB$RAW_LIST_T
 ITEMNUMBER                                         NUMBER(38)
 DESCRIPTION                                        VARCHAR2(256 CHAR)
 PART                                               PART_T

この例では、XML SchemaがOracle XML DBに登録されたときに、SQL型定義が作成されています。次のSQL型定義が含まれます。

  • purchaseorder_t。この型を使用してPurchaseOrder要素から生成されたSQLオブジェクトを永続的に保持します。PurchaseOrder要素を含むXML文書がOracle XML DBに格納される場合、文書は分割され、文書のコンテンツはpurchaseorder_tのインスタンスとして格納されます。

  • lineitems_tlineitem_vおよびlineitem_t。これらの型はPurchaseOrder文書に存在する可能性のあるLineItem要素のコレクションを管理します。型lineitems_tは、型lineitem_vのインスタンスとして定義された単一の属性lineitemで構成されます。型lineitem_vlinteitem_tオブジェクトのVARRAYとして定義されます。文書内の各LineItem要素に対し、lineitem_tオブジェクトのインスタンスが1つずつあります。

大規模なXML Schemaの操作

大規模で複雑なXML Schemaを操作する場合、いくつかの問題が発生することがあります。場合により、XML Schemaを登録する際、またはXML Schemaによって定義されたグローバル要素に基づく表を作成する際に、次のいずれかのエラーが発生することがあります。

  • ORA-01792: 表またはビューに指定できる最大列数は1000です。

  • ORA-04031: 共有メモリーのstringバイトを割当てできません("string","string","string","string")

これらのエラーは、グローバル要素に基づいてXMLType表または列を作成するとき、そのグローバル要素が多数の要素と属性の定義を含むcomplexTypeとして定義されている場合に発生します。これらのエラーはオブジェクト・リレーショナル記憶域を使用するXMLType表または列の作成時にのみ発生します。この場合、表または列はSQL型を使用して永続的に保持され、SQL型により定義された各オブジェクト属性は、基礎となる表の1つの列とみなされます。SQL型に別のSQL型に基づくオブジェクト属性が含まれる場合も、それらの型により定義された属性は基礎となる表の列とみなされます。

すべてのSQL型に含まれるオブジェクト属性の合計数がOracle Databaseの上限の1000列(1つの表で)を超えると、記憶域表は作成できません。complexTypeによって定義された要素と属性の総数が1000に達すると、その型のインスタンスがデータベースに格納される場合、生成されるSQLオブジェクトを管理できる単一の表を作成することはできません。


ヒント:

次の問合せを使用すると、オブジェクト・リレーショナル形式で格納されている特定のXMLType表の列数を特定できます。
SELECT count(*) FROM USER_TAB_COLS WHERE TABLE_NAME = '<the table>'

<the table>は、チェック対象の表です。


エラーORA-01792は、1000列の制限を超えたことを報告するものです。エラーORA-04031は、多数の要素および属性の定義の処理中に、メモリーが不足していることを報告するものです。要素と属性の定義が多すぎるというこの問題を解決するには、記憶域表の作成に使用するSQL型のオブジェクト属性の合計数を減らす必要があります。

削減を成功させるには、次の2つの方法があります。

  • XML文書を管理する複数の XMLTypeを使用する、トップダウン方法の使用。この方法は、指定した記憶域表について、SQL型階層内のSQL属性の数を減らします。いずれの表も管理するオブジェクト属性が1000を超えないかぎり、この問題は解決します。

  • SQL型の階層のSQL属性の数を減らし、XML Schemaにより定義された一部の要素および属性を縮小して、単一CLOB値として格納されるようにする、ボトムアップ方法の使用。

いずれの方法とも、XML Schemaに注釈を付けて、特定のcomplexTypeをデータベースに格納する方法を定義します。

トップダウン方法の場合は、SQLInline = "false"およびdefaultTableという注釈によって、XML文書内の一部のサブ要素が別のXMLType表に行として強制的に格納されます。Oracle XML DBは、XMLTypeREFを使用して2つの表の間の関係を保持します。この手法の適切な候補は、次のいずれかを実行するXML Schemaです。

  • 含まれる各要素がcomplexTypeとして定義される選択を定義

  • 多数の要素および属性の定義を含むcomplexTypeに基づいて要素を定義

ボトムアップ方法では、下位レベルの一部のcomplexType要素をオブジェクトとしてではなくCLOB値として格納することによって、SQLオブジェクト型の属性の数を減らします。これを行うには、complexTypeに注釈を付けるか、SQLType = "CLOB"を指定したcomplexTypeを使用します。

いずれの方法を使用するかは、アプリケーション、およびデータに対して実行される問合せと更新のタイプによって決まります。

グローバル要素の操作

デフォルトでは、XML Schemaがデータベースに登録するときに、Oracle XML DBは、XML Schemaにより定義される各グローバル要素に対してデフォルト表を生成します。

xdb:defaultTable属性を使用して、特定のグローバル要素に対するデフォルト表の名前を指定できます。指定するxdb:defaultTable属性値は、特定のデータベース・ユーザーにより登録されたすべてのスキーマ間で一意である必要があります。一部の要素に対して空でないデフォルト表名を指定しない場合、一意の名前が自動的に付けられます。

しかし実際には、ほとんどの場合、グローバル要素に対してデフォルト表を作成する必要はありません。XMLインスタンス・ドキュメントのルート要素として機能しない要素には、デフォルト表が使用されることはないため、デフォルト表は必要ありません。特に、XML Schemaに多数のグローバル要素定義が含まれている場合は、すべてのグローバル要素に対してデフォルト表を作成すると、プロセッサ時間に大量のオーバーヘッドが発生し、多くの領域が使用される可能性があります。

このため、一般に、どの文書内でもルート要素として使用されないことが確実なグローバル要素(または表外に格納されたローカル要素)に対しては、デフォルト表が作成されないようにすることができます。これを行うには、次のいずれかの方法を実行します。

  • XMLインスタンス・ドキュメントのルート要素として表示されないグローバル要素の定義に、注釈xdb:defaultTable = "" (空の文字列)を追加します。この方法を使用すると、通常はデフォルト表を自動的に作成し、必要な場合にxdb:defaultTable = ""を使用して明示的にデフォルト表の自動作成を禁止できます。

  • XML Schemaの登録時にパラメータGENTABLESFALSEに設定し、インスタンス・ドキュメントのルート要素として正当に表示できる各グローバル要素に対してデフォルト表を手動で作成します。この方法を使用すると、デフォルト表の自動作成は行われません。必要な表のみを手動で作成します。

XML Schemaに基づくXMLType列および表の作成

XML SchemaをOracle XML DBに登録した後は、XMLType列を含む表を定義する場合、またはXMLType表を作成する場合に、そのXML Schemaを参照できます。

XML Schemaに基づくデータを格納するXMLType表または列を作成する際に、記憶域モデルを指定しない場合、使用される記憶域モデルは、参照するXML Schemaの登録時に指定した記憶域モデルです。XML Schemaの登録時に記憶域モデルを指定しなかった場合は、オブジェクト・リレーショナル形式の記憶域が使用されます。

例3-13に、PurchaseOrder要素のデフォルト表である表purchaseorderを手動で作成する方法を示します。

例3-13 XML Schemaに準拠したXMLType表の作成

CREATE TABLE purchaseorder OF XMLType
  XMLSCHEMA "http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd"
  ELEMENT "PurchaseOrder"
  VARRAY "XMLDATA"."ACTIONS"."ACTION"
    STORE AS TABLE action_table 
                   ((PRIMARY KEY (NESTED_TABLE_ID, SYS_NC_ARRAY_INDEX$)))
  VARRAY "XMLDATA"."LINEITEMS"."LINEITEM"
    STORE AS TABLE lineitem_table 
                   ((PRIMARY KEY (NESTED_TABLE_ID, SYS_NC_ARRAY_INDEX$)));

Action要素のコレクションを管理するVARRAYの各メンバーは、Ordered Collection Table、action_tableに格納されます。LineItem要素のコレクションを管理するVARRAYの各メンバーは、Ordered Collection Table、lineitem_tableに行として格納されます。Ordered Collection Tableはヒープに基づいています。PRIMARY KEY指定のため、表には親の列に逆リンクするのに必要な疑似列NESTED_TABLE_IDおよび列SYS_NC_ARRAY_INDEX$が自動的に含まれます。

このCREATE TABLE文は、XML Schema登録の際、パラメータGENTABLESTRUEに設定すると、Oracle XML DBにより自動生成されるCREATE TABLE文と同等です。デフォルトでは、XML Schema注釈storeVarrayAsTableの値はtrueで、XML Schema登録時に、コレクションに対してOrdered Collection Tables(OCT)を自動生成します。このOCTにはシステムが生成した、覚えにくい名前が付けられます。SQL文RENAME TABLEを使用して、わかりやすい名前を付けることができます。

例3-13CREATE TABLE文は、単一レベルのネストが行われている発注書に対応しています。LineItem要素のコレクションを管理するVARRAYは、Ordered Collection Table、lineitem_tableです。

ここで、別のXML Schemaを想定し、Shipment要素のコレクションがShipments要素内にあり、この要素がLineItem要素内にあるとします。この場合は、例3-14に示すように、表を手動で作成できます。

例3-14 ネストしたコレクションのXMLType表の作成

CREATE TABLE purchaseorder OF XMLType
  XMLSCHEMA "http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd"
  ELEMENT "PurchaseOrder"
  VARRAY "XMLDATA"."ACTIONS"."ACTION"
    STORE AS TABLE action_table 
                   ((PRIMARY KEY (NESTED_TABLE_ID, SYS_NC_ARRAY_INDEX$)))
                   VARRAY "XMLDATA"."LINEITEMS"."LINEITEM"
    STORE AS TABLE lineitem_table 
                   ((PRIMARY KEY (NESTED_TABLE_ID, SYS_NC_ARRAY_INDEX$))
                    VARRAY "SHIPMENTS"."SHIPMENT"
                      STORE AS TABLE shipments_table
                                     ((PRIMARY KEY (NESTED_TABLE_ID,
                                                    SYS_NC_ARRAY_INDEX$))));

例3-15に示すように、SQL*PlusのDESCRIBE文を使用すると、XMLType表に関する情報を表示できます。

例3-15 XML Schemaに基づくXMLType表でのDESCRIBEの使用

DESCRIBE purchaseorder
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
TABLE of SYS.XMLTYPE(XMLSchema
"http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd"
Element "PurchaseOrder") STORAGE Object-relational TYPE "PURCHASEORDER_T"

例3-15DESCRIBE文の出力には、purchaseorder表に関する次の情報が表示されます。

  • 表はXMLType表です。

  • 表は、XML Schema PurchaseOrderで定義されたPurchaseOrder文書の格納用に制限されます。

  • この表の行は、データベースに一連のオブジェクトとして格納されます。

  • SQL型purchaseorder_tは、この表のベース・オブジェクトです。

デフォルト表

例3-13のXML Schemaでは、PurchaseOrder表がPurchaseOrder要素のデフォルト表であることが指定されています。XML Schemaに準拠するXML文書を、プロトコルまたはPL/SQLを使用してOracle XML DBリポジトリに挿入すると、そのXML文書のコンテンツはpurchaseorder表に行として格納されます。

XML Schemaをグローバル・スキーマとして登録した場合は、デフォルト表に対する適切なアクセス権をデータベースのすべてのユーザーに付与する必要があります。これによって、ユーザーは、グローバルに登録したXML Schemaに準拠するインスタンス・ドキュメントを操作できるようになります。

XML Schemaインスタンス・ドキュメントの識別

XML文書をXML Schemaに基づくXMLType表または列に挿入する前に、関連付けられているXML Schemaを識別する必要があります。識別するには、次の2つの方法があります。

  • XMLTypeの作成時に明示的にXML Schemaを識別します。これを行うには、XML Schemaの名前をXMLTypeコンストラクタに渡すか、またはXMLTypecreateSchemaBasedXML()メソッドを起動します。

  • XMLSchema-instanceメカニズムを使用して、必要な情報をXML文書に明示的に提供します。このオプションはOracle XML DBを操作する場合に使用できます。

XMLSchema-instanceメカニズムのメリットは、Oracle XML DBリポジトリに挿入されたXML文書が登録済のXML SchemaのインスタンスであることをOracle XML DBプロトコル・サーバーが認識できることです。インスタンス・ドキュメントのコンテンツは、そのXML Schemaで指定されたデフォルト表に自動的に格納されます。

XMLSchema-instanceメカニズムは、W3CのXML Schemaワーキング・グループにより定義されています。この基本は、ターゲットのXMLスキーマを識別する属性をインスタンス・ドキュメントのルート要素に追加することです。これらの属性はXMLSchema-instance名前空間で定義されます。

インスタンス・ドキュメントを特定のXML Schemaで定義されたクラスのメンバーとして識別するには、名前空間宣言をインスタンス・ドキュメントのルート要素に追加して、XMLSchema-instance名前空間を宣言する必要があります。次に例を示します。

xmlns:xsi = http://www.w3.org/2001/XMLSchema-instance

XMLSchema-instance名前空間が宣言され、namespace接頭辞が指定されると、XML Schemaを識別する属性をインスタンス・ドキュメントのルート要素に追加できます。前述の例では、XMLSchema-instance名前空間の名前空間接頭辞がxsiと定義されています。この接頭辞は、XMLSchema-instanceの属性をインスタンス・ドキュメントのルート要素に追加する際に使用できます。

追加する属性は、いくつかの要因によって決定します。noNamespaceSchemaLocationおよびschemaLocationに、その可能性があります。インスタンス・ドキュメントが関連付けられているXML Schemaを識別するには、XML Schemaに応じて、1つまたは両方の属性が必要です。

属性noNamespaceSchemaLocationおよびschemaLocation

ターゲットのXML Schemaでターゲットの名前空間が宣言されていない場合は、noNamespaceSchemaLocation属性を使用してXML Schemaを識別します。この属性の値はスキーマの場所を示すヒントです。この値は、XML Schemaをデータベースに登録するときにPL/SQLプロシージャDBMS_XMLSCHEMA.registerSchemaに渡される一意の識別子です。

XML Schema purchaseOrder.xsdの場合、インスタンス・ドキュメントのルート要素の正しい定義は次のとおりです。

<PurchaseOrder
  xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
  xsi:noNamespaceSchemaLocation=
    "http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd">

ターゲットのXML Schemaでターゲットの名前空間が宣言されている場合は、schemaLocation属性を使用してXML Schemaを識別します。この属性の値は2つの値の組合せで、空白によって区切られています。

  • XML Schemaで宣言されたターゲットの名前空間の値

  • スキーマをデータベースに登録するときにプロシージャDBMS_XMLSCHEMA.registerSchemaに渡される一意の識別子である、スキーマの場所を示すヒント

たとえば、XML Schema PurchaseOrderにターゲットの名前空間宣言が含まれているとします。この場合、スキーマのルート要素は次のようになります。

<xs:schema targetNamespace="http://demo.oracle.com/xdb/purchaseOrder"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:xdb="http://xmlns.oracle.com/xdb"
           version="1.0" xdb:storeVarrayAsTable="true">
   <xs:element name="PurchaseOrder" type="PurchaseOrderType"
               xdb:defaultTable="PURCHASEORDER"/>

この場合、インスタンス・ドキュメントのルート要素の正しい形式は次のとおりです。

<PurchaseOrder
    xnlns="http://demo.oracle.com/xdb/purchaseOrder"
    xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
    xsi:schemaLocation=
      "http://demo.oracle.com/xdb/purchaseOrder
       http://mdrake-lap:8080/source/schemas/poSource/xsd/purchaseOrder.xsd">

複数の名前空間の使用

XML Schemaに複数の名前空間で定義された要素が含まれている場合は、XML SchemaごとにschemaLocation属性のエントリが必要です。各エントリは、名前空間宣言およびスキーマの場所を示すヒントで構成されています。また、各エントリは1つ以上の空白文字で区切られています。主要なXML Schemaでターゲットの名前空間が宣言されていない場合でも、主要なXML Schemaのスキーマの場所を示すヒントを指定するnoNamespaceSchemaLocation属性をインスタンス・ドキュメントに含める必要があります。

データベースを使用したXMLデータ整合性の規定

Oracle XML DBを使用してXMLコンテンツを管理するメリットの1つは、SQLを使用してXML Schemaで提供される機能を補完できることです。SQLおよびXMLの機能と、ルールを規定するデータベースの機能を組み合せることによって、XMLコンテンツを管理する強力なフレームワークとしてデータベースを使用できます。

XMLType表または列に格納できるのは、整形式のXML文書のみです。整形式のXML文書とは、XML宣言で宣言されたXMLバージョンの構文に準拠しているXML文書です。これには、ルート要素が単一か、タグが適切にネストされているかなどが含まれます。さらに、XMLType表または列がXML Schemaに制限される場合、その表または列に格納できるのはXML Schemaに準拠する文書のみです。これ以外のXML文書をXML Schemaに基づくXMLTypeに格納または挿入しようとすると、エラーが発生します。例3-16に、これを示します。

例3-16 不適切なXML文書を挿入しようとした場合に発生するエラー

INSERT INTO purchaseorder
  VALUES (XMLType(bfilename('XMLDIR', 'Invoice.xml'), nls_charset_id('AL32UTF8')))
  VALUES (XMLType(bfilename('XMLDIR', 'Invoice.xml'), nls_charset_id('AL32UTF8')))
          *
ERROR at line 2:
ORA-19007: Schema - does not match expected
http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd.

このようなエラーは、コンテンツが直接XMLType表に挿入されるときにのみ発生します。Oracle XML DBが、XML Schemaにより定義されたクラスのメンバーとして文書を認識していなかったことを示します。スキーマにより定義されたクラスのメンバーとして認識される文書は、次の条件を満たしている必要があります。

  • XML文書のルート要素の名前が、XMLType表または列の定義で使用するグローバル要素の名前と一致する必要があります。

  • XML文書にXMLSchema-instance名前空間の適切な属性が含まれているか、またはXMLTypeコンストラクタかXMLTypecreateSchemaBasedXML()メソッドを使用してXML文書がXML Schemaに明示的に関連付けられている必要があります。

制限されているXML SchemaでtargetNamespaceが宣言されている場合、インスタンス・ドキュメントには、XML Schemaで定義されたtargetNamespaceに文書のルート要素を配置するための適切な名前空間宣言が含まれている必要があります。


注意:

XMLによる制限は、個々のXML文書内で適用されます。データベース(SQL)による制限は、一連のXML文書にわたって適用されます。

XML Schemaの部分検証と全体検証の比較

この項では、XML文書をデータベースに挿入するときに使用する、XML Schemaの部分検証と全体検証の違いについて説明します。

部分検証

バイナリXML記憶域では、XML文書をXML Schemaに基づくXMLType表または列に挿入するたびに、Oracle XML DBはその文書の全体検証を実行します。他のすべてのXML記憶域モデルでは、Oracle XML DBは文書の部分検証のみを実行します。これは、バイナリXML記憶域を除き、XML Schemaの完全な検証はパフォーマンスの面で非常にコストが高くなるためです。

部分検証では、文書内に必須の要素および属性がすべて存在すること、および予期しない要素または属性のないことが確認されるのみです。つまり、XML文書の構造がXML Schemaから導出されたSQLデータ型定義に準拠していることのみが確認されます。部分検証では、インスタンス・ドキュメントがXML Schemaに完全に準拠しているかどうかは確認されません。

例3-17に、オブジェクト・リレーショナル形式で格納されている表PurchaseOrderにXML文書を挿入する間に部分検証が失敗した例を示します。

例3-17 不適切なXML文書の挿入時に発生するエラー(部分検証)

INSERT INTO purchaseorder
  VALUES(XMLType(bfilename('XMLDIR', 'InvalidElement.xml'),
                 nls_charset_id('AL32UTF8')));
  VALUES(XMLType(bfilename('XMLDIR', 'InvalidElement.xml'),
         *
ERROR at line 2:
ORA-30937: No schema definition for 'UserName' (namespace '##local') in parent
'/PurchaseOrder'

全体検証

XMLデータをXML Schemaに基づくバイナリXML記憶域にロードすると、ターゲットXML Schemaに対する全体検証が行われます。これ以外の場合は、記憶域モデルと無関係に、次のいずれかの方法を使用して、XML Schemaに対するXMLインスタンス・ドキュメントの全体検証をいつでも強制的に実行できます。

  • 表レベルのCHECK制約

  • PL/SQLのBEFORE INSERTトリガー

どちらの方法でも、妥当なXML文書のみがXMLType表に格納されることが保証されます。

TABLE CHECK制約を使用する方法のメリットは、コーディングが簡単なことです。この方法のデメリットは、この方法がOracle SQL関数XMLisValidに基づいているため、XML文書が妥当であるかどうかしか示されないことです。XML文書が妥当でない場合、TABLE CHECK制約では、その理由についての情報を提供できません。

BEFORE INSERTトリガーの場合は、必要なコーディングが表レベルの制約よりわずかに多くなります。このトリガーでは、XMLTypeschemaValidate()メソッドを起動してXML文書を検証します。schemaValidate()を使用するメリットは、例外が発生した場合にそのインスタンス・ドキュメントの問題点に関する追加情報が提供されることです。また、BEFORE INSERTトリガーを使用すると、無効な文書が存在する場合に適切な処置を行うことができます。

XML Schemaの全体検証による処理時間とメモリーの消費

バイナリXML記憶域を使用していない場合は、XML Schemaの全体検証を実行すると、多くの処理時間とメモリーが消費されます。このため、XML Schemaの全体検証は、必要なときにのみ実行してください。XML文書を検証するアプリケーションを使用する場合は、全体検証に関連するオーバーヘッドを回避することによって、バイナリ以外のXML記憶域での全体のスループットを向上させることができます。受信するXML文書の妥当性について確認できない場合は、スキーマに対して妥当なXML文書のみがXMLType表または列に含まれていることをデータベースで確認できます。

例3-18に、CHECK制約をXMLType表に追加してXML Schemaの全体検証を実行する方法を示します。例3-18のXML文書InvalidReferenceは、XML Schemaに従った妥当なXML文書ではありません。XML Schemaでは、Reference要素に関連付けられたテキスト・ノードの最小長を18文字とすることが定義されています。この例に示す文書では、ノードの値はSBELL-20021009で、14文字の長さしかありません。部分検証ではこのエラーは捕捉されません。制約またはトリガーがないかぎり、この文書をデータベースに挿入することが可能です。

例3-18 CHECK制約を使用したXML Schemaの全体検証の実施

ALTER TABLE purchaseorder
  ADD CONSTRAINT validate_purchaseorder
  CHECK (XMLIsValid(OBJECT_VALUE) = 1);
 
Table altered.
 
INSERT INTO purchaseorder
  VALUES (XMLType(bfilename('XMLDIR', 'InvalidReference.xml'),
                  nls_charset_id('AL32UTF8')));

INSERT INTO purchaseorder
*
 
ERROR at line 1:
ORA-02290: check constraint (QUINE.VALIDATE_PURCHASEORDER) violated

疑似列OBJECT_VALUEを使用すると、トリガー内からXMLType表のコンテンツにアクセスできます。例3-19は、BEFORE INSERTトリガーを使用して、XMLType表に挿入されるデータが、指定されたXML Schemaに準拠していることを検証する方法を示しています。

例3-19 BEFORE INSERTトリガーを使用したXML Schemaの全体検証の実施

CREATE OR REPLACE TRIGGER validate_purchaseorder
   BEFORE INSERT ON purchaseorder
   FOR EACH ROW
BEGIN
  IF (:new.OBJECT_VALUE IS NOT NULL) THEN :new.OBJECT_VALUE.schemavalidate();
  END IF;
END;
/

INSERT INTO purchaseorder  VALUES (XMLType(bfilename('XMLDIR', 'InvalidReference.xml'),
                  nls_charset_id('AL32UTF8')));
  VALUES (XMLType( bfilename('XMLDIR', 'InvalidReference.xml'),
          *
ERROR at line 2:
ORA-31154: invalid XML document
ORA-19202: Error occurred in XML processing
LSX-00221: "SBELL-20021009" is too short (minimum length is 18)
ORA-06512: at "SYS.XMLTYPE", line 354
ORA-06512: at "QUINE.VALIDATE_PURCHASEORDER", line 3
ORA-04088: error during execution of trigger 'QUINE.VALIDATE_PURCHASEORDER'

SQL制約を使用した参照整合性の規定

W3CのXML Schema勧告では、XML文書のコンテンツを定義するための強力な言語が定義されています。ただし、現在はW3CのXML Schema勧告で扱われていない簡単なデータ管理の概念がいくつかあります。たとえば、要素または属性の値が次のいずれかのプロパティを持っているかを確認できることなどです。

  • XML文書のセット間で一意であること(UNIQUE制約)

  • 現在の文書以外の特定のデータ・ソース内に存在していること(FOREIGN KEY制約)

ただし、Oracle XML DBでは、そうした制約を強制的に適用できます。XMLデータで整合性を規定するために使用するメカニズムは、リレーショナル・データで整合性を規定するためのメカニズムと同じです。一意性と外部キーの関係などの簡単なルールは、制約を指定することによって規定できます。複雑なルールは、データベース・トリガーを指定して規定できます。

Oracle XML DBを使用すると、XML Schema構造体を使用して指定できるルールに加え、データベースを使用して、ビジネス・ルールもXMLコンテンツに実施することができます。データベースでは、XMLが表に直接挿入されているか、Oracle XML DBリポジトリでサポートされているプロトコルの1つを使用してアップロードされているかに関係なく、これらのビジネス・ルールを規定します。

例3-20例3-21および例3-22に、SQL制約を使用して参照整合性を規定する方法を示します。例3-20では、バイナリXMLとして格納されているXMLType表の一意性制約を定義しています。発注書のReference要素を使用して、仮想列を定義します。一意性制約reference_is_uniqueは、ノード/PurchaseOrder/Reference/text()の値が表に格納されたすべての文書間で一意であることを保証しています。

例3-20 仮想列を使用したバイナリXML表の制約

CREATE TABLE po_binaryxml OF XMLType
  XMLTYPE STORE AS BINARY XML
  VIRTUAL COLUMNS
    (c_reference AS (XMLCast(XMLQuery('/PurchaseOrder/Reference'
                                      PASSING OBJECT_VALUE RETURNING CONTENT)
                             AS VARCHAR2(32))));
 
INSERT INTO po_binaryxml SELECT OBJECT_VALUE FROM OE.purchaseorder;

132 rows created.
 
ALTER TABLE po_binaryxml ADD CONSTRAINT reference_is_unique UNIQUE (c_reference);
 
INSERT INTO po_binaryxml
  VALUES (XMLType(bfilename('XMLDIR', 'DuplicateReference.xml'),
                  nls_charset_id('AL32UTF8')));
INSERT INTO po_binaryxml
*
ERROR at line 1:
ORA-00001: unique constraint (OE.REFERENCE_IS_UNIQUE) violated
 

例3-21では、例3-20と同様の一意性制約を定義していますが、標準のデータベース・スキーマOEXMLTypepurchaseorderにおける一意性制約も定義しています。さらに、各発注書のUser要素が、標準データベース表HR.employeesに存在する従業員の電子メール・アドレスであることを要求する外部キー制約を定義しています。OE.purchaseorder表の場合のように、オブジェクト・リレーショナル形式で格納されているXMLデータの場合、制約は、XMLコンテンツを管理するために使用されるSQLデータ型のオブジェクト属性によって指定される必要があります。

例3-21 オブジェクト・リレーショナル形式で格納されているXMLType表の整合性制約とトリガー

ALTER TABLE purchaseorder
  ADD CONSTRAINT reference_is_unique
  UNIQUE (XMLDATA."REFERENCE");
 
ALTER TABLE purchaseorder
  ADD CONSTRAINT user_is_valid
  FOREIGN KEY (XMLDATA."USERID") REFERENCES hr.employees(email);
 
INSERT INTO purchaseorder
  VALUES (XMLType(bfilename('XMLDIR', 'purchaseOrder.xml'),
                  nls_charset_id('AL32UTF8')));
 
INSERT INTO purchaseorder
  VALUES (XMLType(bfilename('XMLDIR', 'DuplicateReference.xml'),
                  nls_charset_id('AL32UTF8')));

INSERT INTO purchaseorder
*
ERROR at line 1:
ORA-00001: unique constraint (QUINE.REFERENCE_IS_UNIQUE) violated
 
INSERT INTO purchaseorder
  VALUES (XMLType(bfilename('XMLDIR', 'InvalidUser.xml'),
                  nls_charset_id('AL32UTF8')));

INSERT INTO purchaseorder
*
ERROR at line 1:
ORA-02291: integrity constraint (QUINE.USER_IS_VALID) violated - parent key not
 found

例3-20と同様に、例3-21の一意性制約reference_is_uniqueが発注書Reference要素の、表に格納されたすべてのドキュメントを通じての一意性を保証しています。外部キー制約user_is_validは、ここで要素Userの値がemployees表のemail列の値に対応することを保証しています。

XML文書DuplicateRefernce.xmlReference要素に関連付けられたテキスト・ノードに、XML文書PurchaseOrder.xml内の対応するノードと同じ値が含まれています。したがって、両方の文書をOracle XML DBに格納しようとすると、制約reference_is_uniqueに違反します。

また、XML文書InvalidUser.xmlUser要素に関連付けられたテキスト・ノードには、値HACKERが含まれています。employees表には、email列の値がHACKERのエントリはありません。この文書をOracle XML DBに格納しようとすると、制約user_is_validに違反します。

XML Schemaに基づくXMLコンテンツがOracle XML DBリポジトリにロードされると、制約およびトリガーを使用して定義された整合性ルールも規定されます。例3-22に、これを示します。FTPなどのプロトコルを使用してXML Schemaに基づくXMLコンテンツがOracle XML DBリポジトリにアップロードされると、データベース整合性も規定されます。

例3-22 FTPを使用してXMLをロードしたときのデータベース整合性の規定

$ ftp localhost 2100
Connected to localhost.
220 mdrake-sun FTP Server (Oracle XML DB/Oracle Database 10g Enterprise Edition
Release 10.1.0.0.0 - Beta) ready.
Name (localhost:oracle10): QUINE
331 Password required for QUINE
Password: password
230 QUINE logged in
ftp> cd /source/schemas
250 CWD Command successful
ftp> put InvalidReference.xml
200 PORT Command successful
150 ASCII Data Connection
550- Error Response
ORA-00604: error occurred at recursive SQL level 1
ORA-31154: invalid XML document
ORA-19202: Error occurred in XML processing
LSX-00221: "SBELL-20021009" is too short (minimum length is 18)
ORA-06512: at "SYS.XMLTYPE", line 333
ORA-06512: at "QUINE.VALIDATE_PURCHASEORDER", line 3
ORA-04088: error during execution of trigger 'QUINE.VALIDATE_PURCHASEORDER'
550 End Error Response
ftp> put InvalidElement.xml
200 PORT Command successful
150 ASCII Data Connection
550- Error Response
ORA-30937: No schema definition for 'UserName' (namespace '##local') in parent
'PurchaseOrder'
550 End Error Response
ftp> put DuplicateReference.xml
200 PORT Command successful
150 ASCII Data Connection
550- Error Response
ORA-00604: error occurred at recursive SQL level 1
ORA-00001: unique constraint (QUINE.REFERENCE_IS_UNIQUE) violated
550 End Error Response
ftp> put InvalidUser.xml
200 PORT Command successful
150 ASCII Data Connection
550- Error Response
ORA-00604: error occurred at recursive SQL level 1
ORA-02291: integrity constraint (QUINE.USER_IS_VALID) violated - parent key not
 found
550 End Error Response

プロトコルを使用して文書をアップロードしているときにエラーが発生すると、Oracle XML DBはクライアントに対して完全なSQLエラー・トレースを提供します。エラーの解析とレポートの方法は、クライアント・アプリケーションに組み込まれたエラー処理によって決まります。たとえば、コマンドラインFTPツールなどのクライアントはOracle XML DBから戻されたエラーをレポートし、Microsoft Windows Explorerなどのクライアントは単に汎用エラー・メッセージをレポートします。


関連項目:


Oracle XML DBを使用したXMLコンテンツに対するDML操作

Oracle XML DBを使用してXMLコンテンツを管理するもう1つの主なメリットは、Oracle Databaseの機能を使用してXMLコンテンツの問合せと更新を行う強力で柔軟な機能が提供されることです。次の機能が含まれます。

  • XML文書内のノードとフラグメントの取出し

  • XML文書内のノードとフラグメントの更新

  • XML文書内の特定ノード上での索引の作成

  • XML文書のコンテンツ全体の索引付け

  • XML文書に特定のノードが含まれるかどうかの判別

XPathおよびOracle XML

Oracle XML DBには、XMLTypeメソッドおよびXML固有のSQL関数が含まれています。それらのメソッドとSQL関数を使用すると、Oracle Databaseに格納されているXMLコンテンツを問合せおよび更新できます。これらのメソッドとSQL関数では、1つまたは複数の必須ノードを識別するために、W3CのXPath勧告が使用されています。XML文書の各ノードは、XPath式によって一意に識別できます。

XPath式は、スラッシュ記号で区切った要素名、属性名およびXPath関数のリストで構成されます。XPath式には、ターゲット・ノードの判別時に検索するツリーのブランチを決定する位置および条件を含めることができます。

XPathを使用したメソッドと関数がサポートされているため、XMLプログラマはOracle XML DBを使用し、標準に準拠した一般的な方法でXML文書を問合せおよび更新できます。


注意:

Oracle SQL関数およびXMLTypeメソッドは、W3C XPath勧告に準拠しています。このことは、XPath式がどのノードもターゲットにしていない場合にXMLデータに適用されると、空のシーケンスが戻される必要があることを示します。この場合にエラーが発生してはいけません

XPath式をXMLデータに適用するOracle SQL関数またはXMLTypeメソッドによって、何が戻されるのかが決まります。たとえば、XPath式の引数のがどのノードもターゲットにしていない場合、SQL/XML関数XMLQueryNULLを戻します。deleteXMLなどの更新のSQL関数は、入力XMLデータを変更せずに戻します。どのノードもターゲットになっていない場合にはエラーが発生することはありませんが、XPath式の引数が、属性ノードやテキスト・ノードなどの適切ではないノードをターゲットにしている場合は、更新のSQL関数でエラーが発生する可能性があります。


Oracle XML DBに格納されたXMLコンテンツの問合せ

この項では、Oracle XML DBの問合せ方法およびXMLコンテンツの取出し方法について説明します。この項の内容は次のとおりです。

XML文書PurchaseOrder

この項では、例3-23のXML文書PurchaseOrderを使用した例を示します。

例3-23 XMLインスタンス・ドキュメントPurchaseOrder

<PurchaseOrder 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation=
    "http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd">
  <Reference>SBELL-2002100912333601PDT</Reference>
  <Actions>
    <Action>
      <User>SVOLLMAN</User>
    </Action>
  </Actions>
  <Reject/>
  <Requestor>Sarah J. Bell</Requestor>
  <User>SBELL</User>
  <CostCenter>S30</CostCenter>
  <ShippingInstructions>
    <name>Sarah J. Bell</name>
    <address>400 Oracle Parkway
      Redwood Shores
      CA
      94065
      USA</address>
    <telephone>650 506 7400</telephone>
  </ShippingInstructions>
  <SpecialInstructions>Air Mail</SpecialInstructions>
  <LineItems>
    <LineItem ItemNumber="1">
      <Description>A Night to Remember</Description>
      <Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
    </LineItem>
    <LineItem ItemNumber="2">
      <Description>The Unbearable Lightness Of Being</Description>
      <Part Id="37429140222" UnitPrice="29.95" Quantity="2"/>
    </LineItem>
    <LineItem ItemNumber="3">
      <Description>Sisters</Description>
      <Part Id="715515011020" UnitPrice="29.95" Quantity="4"/>
    </LineItem>
  </LineItems>
</PurchaseOrder>

疑似列OBJECT_VALUEを使用したXML文書のコンテンツの取出し

疑似列OBJECT_VALUEは、オブジェクト表の値の別名として使用できます。XMLTypeの単一列からなるXMLType表の場合、XML文書全体が取り出されます。(OBJECT_VALUEは、Oracle Database 10gリリース1より前のリリースで使用されていたvalue(x)およびSYS_NC_ROWINFO$別名に換わるものです。)

例3-24では、文書全体が改行なしで正しく出力されるように、SQL*Plus設定のPAGESIZEおよびLONGを使用しています。(読みやすいように、フォーマット出力で示しています。)

例3-24 OBJECT_VALUEを使用したXML文書全体の取出し

SET LONG 10000
SET PAGESIZE 100

SELECT OBJECT_VALUE FROM purchaseorder;
 
OBJECT_VALUE
-----------------------------------------------------------------------
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="http://localhost:8080/source/schemas
/poSource/xsd/purchaseOrder.xsd">
  <Reference>SBELL-2002100912333601PDT</Reference>
  <Actions>
    <Action>
      <User>SVOLLMAN</User>
    </Action>
  </Actions>
  <Reject/>
  <Requestor>Sarah J. Bell</Requestor>
  <User>SBELL</User>
  <CostCenter>S30</CostCenter>
  <ShippingInstructions>
    <name>Sarah J. Bell</name>
    <address>400 Oracle Parkway
Redwood Shores
CA
94065
USA</address>
    <telephone>650 506 7400</telephone>
  </ShippingInstructions>
  <SpecialInstructions>Air Mail</SpecialInstructions>
  <LineItems>
    <LineItem ItemNumber="1">
      <Description>A Night to Remember</Description>
      <Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
    </LineItem>
    <LineItem ItemNumber="2">
      <Description>The Unbearable Lightness Of Being</Description>
      <Part Id="37429140222" UnitPrice="29.95" Quantity="2"/>
    </LineItem>
    <LineItem ItemNumber="3">
      <Description>Sisters</Description>
      <Part Id="715515011020" UnitPrice="29.95" Quantity="4"/>
    </LineItem>
  </LineItems>
</PurchaseOrder>
 
1 row selected.

XMLQUERYを使用したXML文書のフラグメントまたはノードへのアクセス

SQL/XML関数XMLQueryを使用すると、XPath式と一致するノードを抽出できます。結果は、XMLTypeのインスタンスとして戻されます。例3-25に、複数の問合せの例を示します。

例3-25 XMLQUERYを使用したXMLフラグメントへのアクセス

次の問合せは、XPath式と一致するReference要素を含むXMLTypeインスタンスを戻します。

SELECT XMLQuery('/PurchaseOrder/Reference' PASSING OBJECT_VALUE RETURNING CONTENT)
  FROM purchaseorder;

XMLQUERY('/PURCHASEORDER/REFERENCE'PASSINGOBJECT_
-------------------------------------------------
<Reference>SBELL-2002100912333601PDT</Reference>
 
1 row selected.

次の問合せは、LineItemコレクション内の最初のLineItems要素を含むXMLTypeインスタンスを戻します。

SELECT XMLQuery('/PurchaseOrder/LineItems/LineItem[1]'
                PASSING OBJECT_VALUE RETURNING CONTENT)
  FROM purchaseorder;

XMLQUERY('/PURCHASEORDER/LINEITEMS/LINEITEM[1]'PASSINGOBJECT_
-------------------------------------------------------------
<LineItem ItemNumber="1">
  <Description>A Night to Remember</Description>
  <Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
</LineItem>
 
1 row selected.

次の問合せは、XPath式と一致する3つのDescription要素を含むXMLTypeインスタンスを戻します。これらの要素は、単一のXMLTypeインスタンス内のノードとして戻されます。XMLTypeインスタンスはXMLフラグメントなので、単一のルート・ノードを持ちません。

SELECT XMLQuery('/PurchaseOrder/LineItems/LineItem/Description'
                PASSING OBJECT_VALUE RETURNING CONTENT)
  FROM purchaseorder;

XMLQUERY('/PURCHASEORDER/LINEITEMS/LINEITEM/DESCRIPTION'PASSINGOBJECT_
----------------------------------------------------------------------
<Description>A Night to Remember</Description>
<Description>The Unbearable Lightness Of Being</Description>
<Description>Sisters</Description>
 
1 row selected.

XMLCASTおよびXMLQUERYを使用したテキスト・ノードおよび属性値へのアクセス

テキスト・ノードおよび属性値には、SQL/XML標準関数XMLQueryおよびXMLCastを使用してアクセスできます。このためには、XMLQueryに渡されるXPath式は、文書内の単一のテキスト・ノードまたは属性値(リーフ・ノード)を一意に識別する必要があります。例3-26に、複数の問合せを使用する例を示します。

例3-26 XMLCASTおよびXMLQueryを使用したテキスト・ノード値へのアクセス

次の問合せは、対象のXPath式と一致するReference要素に関連付けられたテキスト・ノードの値を戻します。値は、VARCHAR2値として戻されます。

SELECT  XMLCast(XMLQuery('$p/PurchaseOrder/Reference/text()'
                         PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
                AS VARCHAR2(30))
  FROM purchaseorder;
 
XMLCAST(XMLQUERY('$P/PURCHASEO
------------------------------
SBELL-2002100912333601PDT
 
1 row selected.

次の問合せは、LineItem要素に含まれるDescription要素に関連付けられたテキスト・ノードの値を戻します。特定のLineItem要素は、そのId属性値によって指定されます。LineItem要素を識別する述語は、[Part/@Id="715515011020"]です。アットマーク(@)は、Idが要素でなく属性であることを指定します。値は、VARCHAR2値として戻されます。

SELECT XMLCast(
         XMLQuery('$p/PurchaseOrder/LineItems/LineItem[Part/@Id="715515011020"]/Description/text()'
                  PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
               AS VARCHAR2(30))
  FROM purchaseorder;
 
XMLCAST(XMLQUERY('$P/PURCHASEO
------------------------------
Sisters
 
1 row selected.

次の問合せは、最初のLineItem要素に含まれるDescription要素に関連付けられたテキスト・ノードの値を戻します。最初のLineItem要素は、位置述語[1]で示されます。

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/LineItems/LineItem[1]/Description'
                        PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
               AS VARCHAR2(4000))
  FROM purchaseorder;
 
XMLCAST(XMLQUERY('$P/PURCHASEORDER/LINEITEMS/LINEITEM[1]/DESCRIPTION'PASSINGOBJECT_VALUEAS"P"
---------------------------------------------------------------------------------------------
A Night to Remember
 
1 row selected.

関連項目:


XMLEXISTS、XMLCastおよびXMLQueryを使用したXML文書の検索

SQL/XML標準関数XMLExistsは、指定された文書にW3CのXPath式と一致するノードが含まれているかどうかを評価します。関数XMLExistsは、関数に指定されたXPath式によって指定されたノードが文書に含まれている場合はブール値のtrueを、そうでない場合はfalseの値を戻します。XPath式には述語を含めることができるため、XMLExistsは、指定されたノードが文書内に存在するかどうか、および指定された値を持つノードが文書内に存在するかどうかを判断できます。

同様に、SQL WHERE句でSQL/XML関数XMLCastおよびXMLQueryを使用すると、一部のプロパティを満たす文書のみを問合せの結果として戻すことができます。例3-27に、XMLExistsXMLCastおよびXMLQueryを使用して文書を検索する方法を示します。

例3-27 XMLExists、XMLCastおよびXMLQueryを使用したXMLコンテンツの検索

次の問合せでは、XMLExistsを使用して、ルート要素PurchaseOrderの子であるReferenceという要素がXML文書に含まれているかどうかを確認します。

SELECT count(*) FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder/Reference' PASSING OBJECT_VALUE AS "p");

  COUNT(*)
----------
       132

1 row selected.

次の問合せでは、Reference要素に関連付けられたテキスト・ノードの値がSBELL-2002100912333601PDTであるかどうかを確認します。

SELECT count(*) FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");

  COUNT(*)
----------
         1
1 row selected.

この問合せでは、Reference要素に関連付けられたテキスト・ノードの値がSBELL-XXXXXXXXXXXXXXXXXXであるかどうかを確認します。

SELECT count(*) FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-XXXXXXXXXXXXXXXXXX"]'
                  PASSING OBJECT_VALUE AS "p");
 
  COUNT(*)
----------
         0
 
1 row selected.

この問合せでは、XML文書にルート要素PurchaseOrderが含まれているかどうかを確認します。このルート要素に含まれるLineItems要素にはLineItem要素が含まれ、さらにこの要素にはId属性を持つPart要素が含まれている必要があります。

SELECT count(*) FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder/LineItems/LineItem/Part/@Id'
                  PASSING OBJECT_VALUE AS "p");
 
  COUNT(*)
----------
       132
 
1 row selected.

次の問合せでは、XML文書にルート要素PurchaseOrderが含まれているかどうかを確認します。このルート要素に含まれるLineItems要素にはLineItem要素が含まれ、さらにこの要素にはId属性値が715515009058Part要素が含まれている必要があります。

SELECT count(*) FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder/LineItems/LineItem/Part[@Id="715515009058"]'
                  PASSING OBJECT_VALUE AS "p");
 
  COUNT(*)
----------
        21

次の問合せでは、XML文書にルート要素PurchaseOrderが含まれているかどうかを確認します。このルート要素にはLineItem要素が含まれ、さらにこの要素の3番目LineItem要素にはId属性値が715515009058Part要素が含まれます。

SELECT count(*) FROM purchaseorder
  WHERE XMLExists(
          '$p/PurchaseOrder/LineItems/LineItem[3]/Part[@Id="715515009058"]'
          PASSING OBJECT_VALUE AS "p");

  COUNT(*)
----------
         1
1 row selected.

次の問合せは、User要素に関連付けられたテキスト・ノードが文字Sで始まる行のみをSELECT文の結果として戻します。XQueryでは、LIKEを使用した問合せをサポートしていません。

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference' PASSING OBJECT_VALUE AS "p"
                        RETURNING CONTENT)
               AS VARCHAR2(30))
  FROM purchaseorder
  WHERE XMLCast(XMLQuery('$p/PurchaseOrder/User' PASSING OBJECT_VALUE AS "p"
                         RETURNING CONTENT)
                AS VARCHAR2(30))
        LIKE 'S%';
 
XMLCAST(XMLQUERY('$P/PURCHASEORDER
----------------------------------
SBELL-20021009123336231PDT
SBELL-20021009123336331PDT
SKING-20021009123336321PDT
...
36 rows selected.

次の問合せは、XML文書内のノードの値と別の表のデータに基づいて結合を実行します。

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference' PASSING OBJECT_VALUE AS "p"
                        RETURNING CONTENT)
               AS VARCHAR2(30))
  FROM purchaseorder p, hr.employees e
  WHERE XMLCast(XMLQuery('$p/PurchaseOrder/User' PASSING OBJECT_VALUE AS "p"
                         RETURNING CONTENT)
                AS VARCHAR2(30)) = e.email
    AND e.employee_id = 100;
 
XMLCAST(XMLQUERY('$P/PURCHASEOREDER
-----------------------------------
SKING-20021009123336321PDT
SKING-20021009123337153PDT
SKING-20021009123335560PDT
SKING-20021009123336952PDT
SKING-20021009123336622PDT
SKING-20021009123336822PDT
SKING-20021009123336131PDT
SKING-20021009123336392PDT
SKING-20021009123337974PDT
SKING-20021009123338294PDT
SKING-20021009123337703PDT
SKING-20021009123337383PDT
SKING-20021009123337503PDT
 
13 rows selected.

次の問合せは、XMLExistsを使用して、User要素のテキスト・ノードに値SBELLが含まれる行のみをSELECT文の結果として戻します。

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference' PASSING OBJECT_VALUE AS "p"
                        RETURNING CONTENT)
               AS VARCHAR2(30)) "Reference"
  FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder[User="SBELL"]' PASSING OBJECT_VALUE AS "p");

Reference
------------------------------
SBELL-20021009123336231PDT
SBELL-20021009123336331PDT
SBELL-20021009123337353PDT
SBELL-20021009123338304PDT
SBELL-20021009123338505PDT
SBELL-20021009123335771PDT
SBELL-20021009123335280PDT
SBELL-2002100912333763PDT
SBELL-2002100912333601PDT
SBELL-20021009123336362PDT
SBELL-20021009123336532PDT
SBELL-20021009123338204PDT
SBELL-20021009123337673PDT
 
13 rows selected.

例3-28では、SQL/XML関数XMLQueryおよびXMLExistsを使用して、最初のLineItem要素にId 715515009058の注文が含まれるPurchaseOrder要素についてReference要素を検索します。関数XMLExistsWHERE句で使用して、選択する行を決定し、XMLQuerySELECTリストで使用して、選択された文書のどの部分を結果に表示するかを制御します。

例3-28 XMLQueryとXMLExistsを使用したPurchaseOrderのReferenceの検索

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference' PASSING OBJECT_VALUE AS "p"
                        RETURNING CONTENT)
               AS VARCHAR2(30)) "Reference"
  FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder/LineItems/LineItem[1]/Part[@Id="715515009058"]'
                  PASSING OBJECT_VALUE AS "p");

Reference
-------------------------
SBELL-2002100912333601PDT
 
1 row selected.

関連項目:


XMLTABLEを使用したXMLTypeフラグメントでのSQL操作の実行

例3-25は、XPath式と一致する1つ以上のノードを含むXMLTypeインスタンスを戻す方法を示しています。指定されたXPath式と一致するノードが文書に複数含まれている場合、このような問合せでは、一致するすべてのノードが含まれるXMLフラグメントを戻します。XML文書と異なり、XMLフラグメントには、ルート要素である単一の要素はありません。

このような結果は、次の場合に一般的です。

  • コレクションに含まれている一連の要素を取り出す場合。この場合、フラグメント内のすべてのノードは同じタイプです(例3-29を参照)。

  • 対象のXPath式がワイルドカードで終わる場合。この場合、フラグメント内のノードは異なるタイプになることがあります(例3-31を参照)。

SQL/XML関数XMLTableを使用すると、XMLTypeインスタンスに含まれているXMLフラグメントを分割し、コレクション要素データを新しい仮想表に挿入することができ、その後、SQLを結合式などで使用して問い合せることができます。特に、XMLフラグメントを仮想表に変換することにより、複数のノードを戻すXMLQuery式の評価の結果を処理しやすくなります。

例3-29に、PurchaseOrder文書のDescription要素ごとにテキスト・ノードにアクセスする方法を示します。例3-25の単一のXMLフラグメント出力を複数のテキスト・ノードに分割します。

例3-29 XMLTABLEを使用したDescriptionノードへのアクセス

SELECT des.COLUMN_VALUE
  FROM purchaseorder p,
       XMLTable('/PurchaseOrder/LineItems/LineItem/Description'
                PASSING p.OBJECT_VALUE) des
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
COLUMN_VALUE
------------
<Description>A Night to Remember</Description>
<Description>The Unbearable Lightness Of Being</Description>
<Description>Sisters</Description>

3 rows selected.

例3-29では、SQLを使用してテキスト・ノードのコンテンツを処理するために、SQL/XML関数XMLTableを使用してDescriptionノードのコレクションを仮想表に変換します。この仮想表には3つの行があり、単一のDescription要素を持つ単一のXMLTypeインスタンスが各行に含まれています。

XPath式は、Description要素をターゲットにしています。PASSING句では、XPath式を評価するためのコンテキストとしてXMLTypepurchaseorderのコンテンツ(OBJECT_VALUE)を使用することを指定しています。

したがって、XMLTable式はpurchaseorder表に依存します。これは左側結合です。この相関結合によって、アクセスされるpurchaseorder行と、XMLTableによってその行から生成される行は、1対多(1:N)の関係であることが保証されます。この相関結合により、purchaseorder表は、FROMリストのXMLTable式よりも前に記述する必要があります。これは、PASSING句が表の列を参照する場合に一般的な要件です。

仮想表のXMLTypeインスタンスにはそれぞれ、Description要素が1つずつ含まれます。XMLTableCOLUMNS句を使用して、XPath式'Description'のターゲットのデータを、SQLデータ型VARCHAR2(256)descriptionという列に分割できます。この列を定義する'Description'式は、コンテキストのXPath式'/PurchaseOrder/LineItems/LineItem'相対的です。

SELECT des.description
  FROM purchaseorder p,
       XMLTable('/PurchaseOrder/LineItems/LineItem' PASSING p.OBJECT_VALUE
                COLUMNS description VARCHAR2(256) PATH 'Description') des
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");

DESCRIPTION
---------------------------------
A Night to Remember
The Unbearable Lightness Of Being
Sisters
 
3 rows selected.

COLUMNS句を使用すると、正確なSQLデータ型を指定できるため、静的型チェックがさらに便利になります。この例では、単一の列(description)のみを使用します。XMLType表に複数レベルで含まれているデータをリレーショナル・ビューの個別の行として公開するには、分割してリレーショナル列に格納する各文書レベルにXMLTableを適用します。この例は、例3-33を参照してください。

例3-30では、コレクション内の要素数をカウントします。また、ORDER BYGROUP BYなどのSQLキーワードをSQL/XML関数XMLTableによって作成された仮想表データに適用する方法も示しています。

例3-30 XMLTABLEを使用したコレクション内の要素数のカウント

SELECT reference, count(*)
  FROM purchaseorder,
       XMLTable('/PurchaseOrder' PASSING OBJECT_VALUE
                COLUMNS reference VARCHAR2(32) PATH 'Reference',
                        lineitem  XMLType      PATH 'LineItems/LineItem'),
       XMLTable('LineItem' PASSING lineitem)
  WHERE XMLExists('$p/PurchaseOrder[User="SBELL"]'
                  PASSING OBJECT_VALUE AS "p")
  GROUP BY reference
  ORDER BY reference;

REFERENCE                    COUNT(*)
--------------------------   --------
SBELL-20021009123335280PDT         20
SBELL-20021009123335771PDT         21
SBELL-2002100912333601PDT           3
SBELL-20021009123336231PDT         25
SBELL-20021009123336331PDT         10
SBELL-20021009123336362PDT         15
SBELL-20021009123336532PDT         14
SBELL-20021009123337353PDT         10
SBELL-2002100912333763PDT          21
SBELL-20021009123337673PDT         10
SBELL-20021009123338204PDT         14
SBELL-20021009123338304PDT         24
SBELL-20021009123338505PDT         20

13 rows selected.

例3-30の問合せでは、SQL/XML関数XMLExistsへのXPath式と一致する一連のXML文書が検索されます。これにより、次の2つの列を含む仮想表が生成されます。

  • reference: この列には、選択された各文書のReferenceノードが含まれます。

  • lineitem: この列には、選択された各文書の一連のLineItemノードが含まれます。

文書ごとにLineItemノードの数がカウントされます。相関結合によって、GROUP BYLineItem要素が属するPurchaseOrder要素を正しく判別できます。

例3-31では、SQL/XML関数XMLTableを使用して、指定された要素の要素の数をカウントする方法を示します。XMLTableに渡されるXPath式には、PurchaseOrder要素の直接の子孫である全要素と一致するワイルド・カード(*)が含まれます。XMLTableで作成された仮想表の各行には、XPath式と一致するノードが含まれます。仮想表内の行数をカウントすることによって、要素PurchaseOrderの子要素の数が判明します。

例3-31 XMLTABLEを使用した要素内の子要素数のカウント

SELECT count(*)
  FROM purchaseorder p, XMLTable('/PurchaseOrder/*' PASSING p.OBJECT_VALUE)
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
  COUNT(*)
----------
         9

1 row selected.

リレーショナル・ビューを使用したOracle XML DB内のXMLデータへのアクセス

Oracle XML DBで提供されるXML特有の関数およびメソッドを使用すると、XMLコンテンツへのリレーショナル・アクセスを提供する、従来のリレーショナル・ビューを作成できます。これによって、Oracle Databaseには対処していてもXMLには対処していないプログラマ、ツールおよびアプリケーションでも、データベースに格納されたXMLコンテンツを操作できます。

リレーショナル・ビューでは、XPath式とXMLTableなどのSQL/XML問合せおよびアクセス関数を使用して、ビューの列とXML文書のノードとの間のマッピングを定義できます。XML文書が、CLOBインスタンスとしてではなく、構造化(オブジェクト・リレーショナル)XML記憶域またはバイナリXML記憶域を使用して格納されている場合のみ、パフォーマンス上の理由からこの方法をお薦めします。


関連項目:


単一レベルのXMLデータの分割

XMLType表内の各文書をリレーショナル・ビューの行として公開する必要がある場合は、次の方法を使用できます。

  1. CREATE OR REPLACE VIEWを使用して、ビューを構成する一連の列を定義します。

  2. XML文書内のノードを、ビューで定義されている列にマップします。このためには、SQL/XML関数XMLTableを適切なXPath式とともに使用して、ノードを抽出します。

この方法は、XMLType表内の文書とビュー内の行の間に、1対1 (1:1)の関係がある場合はいつでも使用できます。

例3-32では、XMLコンテンツを公開する簡単なリレーショナル・ビューpurchaseorder_master_viewの作成方法を示します。このビューには、XMLTypepurchaseorderの行ごとに1つの行が含まれます。

例3-32 XMLコンテンツのリレーショナル・ビューの作成

CREATE OR REPLACE VIEW purchaseorder_master_view AS
  SELECT po.*
    FROM purchaseorder pur,
         XMLTable(
           '$p/PurchaseOrder' PASSING pur.OBJECT_VALUE as "p"
           COLUMNS
             reference       VARCHAR2(30)   PATH 'Reference',
             requestor       VARCHAR2(128)  PATH 'Requestor',
             userid          VARCHAR2(10)   PATH 'User',
             costcenter      VARCHAR2(4)    PATH 'CostCenter',
             ship_to_name    VARCHAR2(20)   PATH 'ShippingInstructions/name',
             ship_to_address VARCHAR2(256)  PATH 'ShippingInstructions/address',
             ship_to_phone   VARCHAR2(24)   PATH 'ShippingInstructions/telephone',
             instructions    VARCHAR2(2048) PATH 'SpecialInstructions') po;

View created.

DESCRIBE purchaseorder_master_view

Name            Null?    Type
--------------------------------------------
REFERENCE                VARCHAR2(30)
REQUESTOR                VARCHAR2(128)
USERID                   VARCHAR2(10)
COSTCENTER               VARCHAR2(4)
SHIP_TO_NAME             VARCHAR2(20)
SHIP_TO_ADDRESS          VARCHAR2(256)
SHIP_TO_PHONE            VARCHAR2(24)
INSTRUCTIONS             VARCHAR2(2048)

複数レベルのXMLデータの分割

XMLType表に複数レベルで含まれているデータをリレーショナル・ビューの個別の行として公開する必要がある場合は、単一レベルの分割と同じ一般的な方法を使用し、1)ビューを構成する列の定義、および、2)列へのXMLノードのマップを行います。ただし、この場合は、分割してリレーショナル列に格納する各文書レベルにXMLTableを適用します。

この方法は、XMLType表内の文書とビュー内の行の間に、1対 (1:N)関係がある場合はいつでも使用できます。

たとえば、各PurchaseOrder要素にLineItems要素が含まれていて、この要素に1つ以上のLineItem要素が含まれているとします。各LineItem要素には、DescriptionItemNumber属性などの子要素があります。このような下位レベルのデータをリレーショナル値としてアクセス可能にするには、PurchaseOrder要素とLineItemコレクションの両方を分割する必要があります。この分割は、いずれもXMLTableを使用して行われます。要素PurchaseOrderを分割すると、LineItem要素は、XMLフラグメントが含まれている型XMLTypeのリレーショナル列にマップされます。この列は次に、XMLTypeへの2回目のコールに渡され、リレーショナル値の複数の行として複数の部分に分割されます。

例3-33に、これを示します。この例では、XMLTypepurchaseorder内の文書とビューの行の間に1対(1:N)の関係がある場合の、SQL/XML関数XMLTableの使用方法を示します。このビューはコレクションの個別のメンバーへのアクセスを提供し、コレクション・メンバーを行のセットとして公開します。

例3-33 ビューを使用したコレクションの各メンバーへのアクセス

CREATE OR REPLACE VIEW purchaseorder_detail_view AS
  SELECT po.reference, li.*
    FROM purchaseorder p,
         XMLTable('/PurchaseOrder' PASSING p.OBJECT_VALUE
                  COLUMNS
                    reference VARCHAR2(30) PATH 'Reference',
                    lineitem  XMLType      PATH 'LineItems/LineItem') po,
         XMLTable('/LineItem' PASSING po.lineitem
                  COLUMNS
                    itemno      NUMBER(38)    PATH '@ItemNumber',
                    description VARCHAR2(256) PATH 'Description',
                    partno      VARCHAR2(14)  PATH 'Part/@Id',
                    quantity    NUMBER(12, 2) PATH 'Part/@Quantity',
                    unitprice   NUMBER(8, 4)  PATH 'Part/@UnitPrice') li;

View created.

DESCRIBE purchaseorder_detail_view
Name           Null?    Type
----------------------------
REFERENCE               VARCHAR2(30)
ITEMNO                  NUMBER(38)
DESCRIPTION             VARCHAR2(256)
PARTNO                  VARCHAR2(14)
QUANTITY                NUMBER(12,2)
UNITPRICE               NUMBER(8,4)

例3-33では、ビューpurchaseorder_detail_viewの各行は、XMLTypepurchaseorderに格納されているXML文書内の各LineItem要素に対応しています。

CREATE OR REPLACE VIEW文では、ビューを構成する一連の列を定義します。SELECT文は、コンテキストとしてpurchaseorder表を関数XMLTableに渡し、列referenceおよびlineitemを含む、仮想表pを作成します。これらの列には、発注書のReferenceおよびLineItem要素がそれぞれ含まれます。

lineitemにはLineItem要素のコレクションがXMLTypeインスタンスとして含まれ、各行が各LineItem要素に対応します。これらの行は次に、2つ目のXMLTable式に渡され、そのコンテキストとして機能します。この2つ目のXMLTable式により、明細/項目行の仮想表が作成され、各列が要素LineItemの様々な子孫ノードに対応します。これらの子孫の大半は属性(ItemNumberPart/@Idなど)です。子孫の1つはDescription子要素です。

Reference要素は列referenceとしてビューpurchaseorder_detail_viewに含まれます。ビューpurchaseorder_detail_viewの行をビューpurchaseorder_master_viewの対応する行に結合するのに使用できる外部キーを提供します。CREATE VIEW文の相関結合によって、ビューにアクセスするたびに、Reference要素と、関連するLineItem要素の間の1対多(1:N)の関係が保持されます。

リレーショナル・データとしてのXMLコンテンツの問合せ

この項の例では、XMLデータのリレーショナル問合せについて説明します。これらの例では、XMLType表および列に対してリレーショナル・ビューを作成するメリットをいくつか示します。

例3-34に、XMLデータのマスターおよび詳細なリレーショナル・ビューの問合せ方法を示します。

例3-34 ビューを使用したXMLデータの問合せ

マスター・ビューに対する次の単純な問合せでは、従来のSELECT文を使用して、userid列がSで始まる行を戻します。

SELECT reference, costcenter, ship_to_name
  FROM purchaseorder_master_view
  WHERE userid LIKE 'S%';
 
REFERENCE                      COST SHIP_TO_NAME
------------------------------ ---- --------------
SBELL-20021009123336231PDT     S30  Sarah J. Bell
SBELL-20021009123336331PDT     S30  Sarah J. Bell
SKING-20021009123336321PDT     A10  Steven A. King
...
36 rows selected.

次の問合せは、マスター・ビューと詳細ビューの結合に基づいています。従来のSELECT文により、itemno列の値が1で、対応するpurchaseorder_master_viewの行に値がSBELLuserid列が含まれているpurchaseorder_detail_viewの行を検索します。

SELECT d.reference, d.itemno, d.partno, d.description
  FROM purchaseorder_detail_view d, purchaseorder_master_view m
  WHERE m.reference = d.reference
    AND m.userid = 'SBELL'
    AND d.itemno = 1;

REFERENCE                          ITEMNO PARTNO         DESCRIPTION
------------------------------ ------------------------------------------------
SBELL-20021009123336231PDT              1 37429165829    Juliet of the Spirits
SBELL-20021009123336331PDT              1 715515009225   Salo
SBELL-20021009123337353PDT              1 37429141625    The Third Man
SBELL-20021009123338304PDT              1 715515009829   Nanook of the North
SBELL-20021009123338505PDT              1 37429122228    The 400 Blows
SBELL-20021009123335771PDT              1 37429139028    And the Ship Sails on
SBELL-20021009123335280PDT              1 715515011426   All That Heaven Allows
SBELL-2002100912333763PDT               1 715515010320   Life of Brian - Python
SBELL-2002100912333601PDT               1 715515009058   A Night to Remember
SBELL-20021009123336362PDT              1 715515012928   In the Mood for Love
SBELL-20021009123336532PDT              1 37429162422    Wild Strawberries
SBELL-20021009123338204PDT              1 37429168820    Red Beard
SBELL-20021009123337673PDT              1 37429156322    Cries and Whispers

13 rows selected.

例3-34のビューの外観と動作は、標準のリレーショナル・ビューと同様です。このビューは、標準のリレーショナル構文を使用して問合せできます。問合せまたは生成される結果セットでは、XML固有の構文は必要ありません。

Oracle XML DBでは、ビジネス・インテリジェンスや分析機能などの高度なデータベース機能がXML対応でない場合でも、XMLコンテンツをリレーショナル・データとして公開することによって、これらの機能をXMLコンテンツに適用できます。

例3-35では、XMLコンテンツのリレーショナル・ビューを使用して、XML文書のビジネス・インテリジェンス問合せを実行する方法を示します。この例の問合せは、タイトルがUPCコード715515009058および715515009126で識別される発注を含むPurchaseOrder文書を選択します。

例3-35 ビューを使用したXMLデータのビジネス・インテリジェンス問合せ

SELECT partno, count(*) "No of Orders", quantity "No of Copies"
  FROM purchaseorder_detail_view
  WHERE partno IN (715515009126, 715515009058)
  GROUP BY rollup(partno, quantity);
 
PARTNO         No of Orders No of Copies
-------------- ------------ ------------
715515009058              7            1
715515009058              9            2
715515009058              5            3
715515009058              2            4
715515009058             23
715515009126              4            1
715515009126              7            3
715515009126             11
                         34 
9 rows selected.

例3-35の問合せは、PurchaseOrder文書ごとに、発注された各タイトルのコピー数を判別します。部品番号715515009126には、発注された品目のコピー数が1のPurchaseOrder文書は4つあり、発注された品目のコピー数が3のPurchaseOrder文書は7つあります。

Oracle XML DBに格納されたXMLコンテンツの更新

Oracle XML DBでは、XMLコンテンツに対する更新操作を実行できます。更新操作では、文書のコンテンツ全体または文書の一部を置き換えることができます。XML文書を部分的に更新する機能は非常に強力で、特に大きな文書に小さな変更を行う場合に、更新の実行に必要なネットワーク・トラフィックとディスクの入出力を大幅に削減できます。

SQL関数updateXMLを使用すると、XMLTypeインスタンスとして格納されたXML文書の部分的な更新が可能になります。これにより、文書に対する複数の変更を1回の操作で実行できます。各変更は、更新するノードを識別するXPath式と、ノードの新しい値で構成されます。

例3-36では、SQL関数updateXMLを使用して、要素Userに関連付けられたテキスト・ノードを更新します。

例3-36 UPDATEXMLを使用したXMLコンテンツの更新

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/User' PASSING OBJECT_VALUE AS "p"
                                                RETURNING CONTENT)
               AS VARCHAR2(60))
  FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
XMLCAST(XMLQUERY('$P/PURCHAS
----------------------------
SBELL
 
1 row selected.
 
UPDATE purchaseorder
SET OBJECT_VALUE =
    updateXML(OBJECT_VALUE, '/PurchaseOrder/User/text()', 'SKING')
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
1 row updated.

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/User' PASSING OBJECT_VALUE AS "p"
                                                RETURNING CONTENT)
               AS VARCHAR2(60))
  FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
XMLCAST(XMLQUERY('$P/PURCHAS
----------------------------
SKING

1 row selected.

例3-37では、SQL関数updateXMLを使用して、XML文書内の要素全体を置換します。XPath式によって要素が参照され、置換値はXMLTypeオブジェクトとして渡されます。

例3-37 UPDATEXMLを使用した要素全体の置換

SELECT XMLQuery('$p/PurchaseOrder/LineItems/LineItem[1]'
                PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
  FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
XMLQUERY('$P/PURCHAS
--------------------
<LineItem ItemNumber="1">
  <Description>A Night to Remember</Description>
  <Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
</LineItem>
 
1 row selected.
 
UPDATE purchaseorder
  SET OBJECT_VALUE = 
        updateXML(
          OBJECT_VALUE,
          '/PurchaseOrder/LineItems/LineItem[1]',
          XMLType('<LineItem ItemNumber="1">
                     <Description>The Lady Vanishes</Description>
                     <Part Id="37429122129" UnitPrice="39.95" Quantity="1"/>
                   </LineItem>'))
    WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                    PASSING OBJECT_VALUE AS "p");
 
1 row updated.

SELECT XMLQuery('$p/PurchaseOrder/LineItems/LineItem[1]'
                PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
  FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");

XMLQUERY('$P/PURCHAS
--------------------
<LineItem ItemNumber="1">
  <Description>The Lady Vanishes</Description>
  <Part Id="37429122129" UnitPrice="39.95" Quantity="1"/>
</LineItem>
 
1 row selected.

例3-38に、コレクション内で複数回出現するノードを、SQL関数updateXMLを使用して更新する際に発生する一般的なエラーを示します。UPDATE文で、Description要素のテキスト・ノードの値をThe Wizard of Ozに設定します。この現在のテキスト・ノードの値はSistersです。この文のWHERE句にはXMLExists式が含まれ、更新する一連のノードを識別します。

例3-38 コレクション内で複数回出現するノードの間違った更新

SELECT XMLCast(des.COLUMN_VALUE AS VARCHAR2(256))
  FROM purchaseorder,
       XMLTable('$p/PurchaseOrder/LineItems/LineItem/Description'
                PASSING OBJECT_VALUE AS "p") des
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
XMLCAST(DES.COLUMN_VALUEASVARCHAR2(256))
----------------------------------------
The Lady Vanishes
The Unbearable Lightness Of Being
Sisters
 
3 rows selected.
 
UPDATE purchaseorder p
  SET p.OBJECT_VALUE =
        updateXML(p.OBJECT_VALUE,
                  '/PurchaseOrder/LineItems/LineItem/Description/text()',
                  'The Wizard of Oz')
    WHERE XMLExists('$p/PurchaseOrder/LineItems/LineItem[Description="Sisters"]'
                    PASSING OBJECT_VALUE AS "p")
      AND XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                    PASSING OBJECT_VALUE AS "p");
 
1 row updated.

SELECT XMLCast(des.COLUMN_VALUE AS VARCHAR2(256))
  FROM purchaseorder,
       XMLTable('$p/PurchaseOrder/LineItems/LineItem/Description'
                PASSING OBJECT_VALUE AS "p") des
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
XMLCAST(DES.COLUMN_VALUEASVARCHAR2(256))
----------------------------------------
The Wizard of Oz
The Wizard of Oz
The Wizard of Oz
 
3 rows selected.

例3-38では、SQL関数updateXMLは、目的のノードのみを更新するのではなく、Description要素に属するすべてのテキスト・ノードの値を更新します。これはupdateXMLの正しい動作ですが、意図していたものではありません。

WHERE句は、更新が必要な文書識別するためにのみ使用できその文書内で更新が必要なノード識別には使用できません

文書が選択されると、updateXMLに渡されるXPath式により、文書内で更新が必要なノードが判別されます。この例では、XPath式によって3つすべてのDescriptionノードが識別されるため、関連する3つのテキスト・ノードすべてが更新されています。

SQL関数updateXMLを正しく使用してコレクション内で複数回出現するノードを更新するには、updateXMLに渡されるXPath式を使用して、XML文書内の更新対象のノードを識別します。XPath式に適切な述語を設定することによって、文書内の更新対象のノードを限定できます。例3-39では、コレクション内の1つのノードを更新する正しい方法を示します。

例3-39 コレクション内で複数回出現するノードの正しい更新

SELECT XMLCast(des.COLUMN_VALUE AS VARCHAR2(256))
  FROM purchaseorder,
       XMLTable('$p/PurchaseOrder/LineItems/LineItem/Description'
                PASSING OBJECT_VALUE AS "p") des
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
XMLCAST(DES.COLUMN_VALUEASVARCHAR2(256))
----------------------------------------

A Night to Remember
The Unbearable Lightness Of Being
Sisters

3 rows selected.

UPDATE purchaseorder p
 SET p.OBJECT_VALUE = 
       updateXML(
         p.OBJECT_VALUE,
         '/PurchaseOrder/LineItems/LineItem/Description[text()="Sisters"]/text()',
         'The Wizard of Oz')
 WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                 PASSING OBJECT_VALUE AS "p");

1 row updated.

SELECT XMLCast(des.COLUMN_VALUE AS VARCHAR2(256))
  FROM purchaseorder,
       XMLTable('$p/PurchaseOrder/LineItems/LineItem/Description'
                PASSING OBJECT_VALUE AS "p") des
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
XMLCAST(DES.COLUMN_VALUEASVARCHAR2(256))
----------------------------------------
A Night to Remember
The Unbearable Lightness Of Being
The Wizard of Oz
 
3 rows selected.

SQL関数updateXMLを使用すると、文書に対する複数の変更を1つの文で実行できます。例3-40では、User要素およびSpecialInstructions要素に属するテキスト・ノードの値を1つの文で変更する方法を示します。

例3-40 UPDATEXMLを使用したテキスト・ノード値の変更

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/CostCenter'
                        PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
               AS VARCHAR2(4)) "Cost Center",
       XMLCast(XMLQuery('$p/PurchaseOrder/SpecialInstructions'
                        PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
               AS VARCHAR2(2048)) "Instructions"
  FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");

Cost Center  Instructions
------------ ------------
S30          Air Mail
 
1 row selected.

次の単一のUPDATE SQL文により、User要素およびSpecialInstructions要素のテキスト・ノード値が変更されます。

UPDATE purchaseorder
  SET OBJECT_VALUE =
        updateXML(OBJECT_VALUE,
                  '/PurchaseOrder/CostCenter/text()',
                  'B40',
                  '/PurchaseOrder/SpecialInstructions/text()',
                  'Priority Overnight Service')
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
1 row updated.

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/CostCenter'
                        PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
               AS VARCHAR2(4)) "Cost Center",
       XMLCast(XMLQuery('$p/PurchaseOrder/SpecialInstructions'
                        PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
               AS VARCHAR2(2048)) "Instructions"
  FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
Cost Center  Instructions
------------ --------------------------
B40          Priority Overnight Service
 
1 row selected.

XML Schemaに基づくXML文書および基づかないXML文書の更新

updateXMLなどのSQL関数がXML文書を変更する方法は、XML文書の格納方法と、XML Schemaに基づいているかどうかにより異なります。

  • CLOB値で格納されたXML文書: CLOBとして格納されたXML Schemaに基づくXML文書または基づかないXML文書をupdateXMLなどのSQL関数で更新すると、Oracle XML DBは、その文書からドキュメント・オブジェクト・モデル(DOM)を作成し、DOM APIメソッドを使用して適切なXMLデータを更新することで、更新を実行します。更新後、更新されたDOMは基礎となるCLOB値に戻されます。

  • オブジェクト・リレーショナル形式で格納されたXML文書: オブジェクト・リレーショナル形式で格納されたXML Schemaに基づくXML文書をupdateXMLなどのSQL関数で更新すると、Oracle XML DBはXPathリライトを使用して、基礎となるオブジェクトのインプレース更新を実行できます。これは部分更新で、SQL関数へのXPath引数が同等のSQL操作に変換されます。すると、SQL操作によって基礎となるオブジェクトの属性が直接更新されます。このような部分更新は、DOMベースの更新よりもはるかに短時間で実行できます。このため、updateXMLなどのSQL関数を多数の文書に適用するSQLコードを実行すると、処理速度を大幅に改善できる場合があります。

  • バイナリXML文書として格納されたXML文書: updateXMLなどのSQL関数をバイナリXML列で使用する場合、Oracle XML DBでは多くの場合、DOMを作成する必要はありません。文書中で更新が必要とされる正確な部分は、ストリーミングおよびXMLIndexなどの問合せ評価手法を使用して計算されます。更新されたデータは、最初の変更の発生箇所以降のみがディスクに書き込まれます。それ以前の変更はすべて変更されません。さらに、データの格納にSecureFile LOBが使用される(デフォルトの動作)場合、変更はスライド方式で適用され、残りのLOBのリライトは行われません。つまり、XMLデータのSecureFile LOB記憶域では、実際に変更されたデータのみが更新されます。これにより、非構造化記憶域と比べて、パフォーマンスが大幅に向上する可能性があります。これらの最適化は、XML Schemaに基づかないデータと基づくデータの両方に適用されます。

Oracle XML DBでの名前空間のサポート

名前空間のサポートは、W3CのXML勧告の主要な特徴です。Oracle XML DBでは、W3Cの名前空間勧告を完全にサポートしています。XMLTypeメソッドおよびXML固有のSQL関数はすべて、名前空間接頭辞を含むXPath式で使用できます。XPath式で使用する名前空間接頭辞を正しく解決するために、すべてのメソッドおよび関数は、名前空間宣言を指定するオプションのnamespace引数を受け入れます。指定されたXPath式に名前空間接頭辞が含まれている場合は、常にnamespaceパラメータが必要です。パラメータnamespaceが指定されている場合は、デフォルトの名前空間がnoNamespace名前空間でないかぎり、このパラメータでデフォルトの名前空間と接頭辞付き名前空間を明示的に宣言する必要があります。パラメータnamespaceが指定されていない場合、Oracle XML DBでは、XPath式について次のことを前提とします。

  • XMLTypeインスタンスのコンテンツが登録済のXML Schemaに基づいていない場合、名前空間接頭辞を含むXPath式内の要素はすべてnoNamespace名前空間に存在すると想定されます。

  • XMLTypeのコンテンツが登録済のXML Schemaに基づいている場合、名前空間接頭辞を含まないXPath式内の要素はすべて、XML Schemaで宣言されたtargetNamespaceがあれば、その名前空間に存在すると想定されます。XML Schemaでtargetnamespaceが宣言されていない場合は、名前noNamespaceが使用されます。

XPath式の解決に必要な名前空間を正しく定義しないと、XPathを使用した操作が予測どおりに機能しません。名前空間の宣言が正しくないか存在しない場合、操作の結果はエラーではなくNULLになります。混乱を避けるために、noNamespace以外の名前空間がXPath式またはターゲットXML文書のいずれかに存在する場合は必ず、デフォルト名前空間宣言を含む、一連の名前空間宣言をすべて渡します。

Oracle XML DBでのXMLTypeメソッドおよびSQL関数の処理

Oracle XML DBは、DOMベースまたはSQLベースの方法を使用して、XMLQueryメソッドやXMLTypeメソッドなどのSQL/XMLアクセスおよび問合せ関数を処理します。

  • DOMベースのXMLTypeの処理: Oracle XML DBはXMLTypeオブジェクトのコンテンツからDOMを構成することで、必要な処理を実行します。DOM APIで提供されるメソッドを使用して、DOMで必要な処理を実行します。DOMツリーの更新が含まれる操作を実行する場合は、操作の完了時にXML文書全体をディスクに再書込みする必要があります。XMLTypeデータに対してDOMベースの操作を使用する処理は、機能上の評価と呼ばれます。

    機能上の評価のメリットは、記憶域モデル(構造化、バイナリXMLまたは非構造化)に関係なく、XMLTypeインスタンスに使用できることです。機能上の評価のデメリットは、XPathリライトよりもコストがかかることと、多数のXML文書間でのスケーラビリティがないことです。

  • SQLベースのXMLType処理: Oracle XML DBは、関数またはメソッドの完了に必要な処理を実行するSQL文を構成します。SQL文は、XML Schemaに基づくXMLTypeの基礎となるオブジェクト・リレーショナル・データ構造に対して直接機能します。このプロセスは、XPathリライトと呼ばれます。第8章「構造化記憶域のXPathリライト」を参照してください。

    XPathリライトのメリットは、Oracle XML DBによって、XPathを使用したSQL関数およびメソッドをリレーショナルとほぼ同じ速度で評価できることです。これにより、操作では多数のXML文書間でスケーラビリティを持つことができます。XPathリライトのデメリットは、XML文書を格納するのに使用するオブジェクトに直接アクセスして更新するため、XML Schemaに基づくオブジェクト・リレーショナル記憶域テクニックを使用してXMLTypeインスタンスを格納した場合にしか使用できないことです。

  • バイナリXMLデータのストリーム式の評価: バイナリXMLをXMLType記憶域モデルとして使用する場合、XMLQueryなどのSQL/XMLアクセスおよび問合せ関数で使用されるXPath式は、DOMの構築に依存せずにストリーム方式で評価されます。

リレーショナル・データからのXMLデータの生成

この項では、Oracle XML DBを使用してリレーショナル・データからXMLデータを生成する例を紹介します。

SQL/XML関数を使用した、リレーショナル・データからのXMLデータの生成

標準のSQL/XML関数を使用すると、XML文書を1つ以上生成できます。SQL/XML関数XMLQueryは、これを行うための最も一般的な方法です。この操作に使用できるSQL/XML関数には、他に次のものがあります。

  • XMLElementは、要素を作成します。

  • XMLAttributesは、属性を要素に追加します。

  • XMLForestは、要素のフォレストを作成します。

  • XMLAggは、要素のコレクションから単一の要素を作成します。

例3-41の問合せでは、これらの関数を使用して、表departmentslocationscountriesemployeesおよびjobsの情報を含むXML文書を生成します。

例3-41 SQL/XML関数を使用したXMLデータの生成

SELECT XMLElement(
         "Department",
         XMLAttributes(d.Department_id AS "DepartmentId"),
         XMLForest(d.department_name AS "Name"),
         XMLElement(
           "Location",
           XMLForest(street_address AS "Address",
                     city AS "City",
                     state_province AS "State",
                     postal_code AS "Zip",
                     country_name AS "Country")),
           XMLElement(
             "EmployeeList",
             (SELECT XMLAgg(
                       XMLElement(
                         "Employee",
                         XMLAttributes(e.employee_id AS "employeeNumber"),
                         XMLForest(
                           e.first_name AS "FirstName", 
                           e.last_name AS "LastName",
                           e.email AS "EmailAddress",
                           e.phone_number AS "PHONE_NUMBER",
                           e.hire_date AS "StartDate",
                           j.job_title AS "JobTitle",
                           e.salary AS "Salary",
                           m.first_name || ' ' || m.last_name AS "Manager"),
                         XMLElement("Commission", e.commission_pct)))
                FROM hr.employees e, hr.employees m, hr.jobs j
                WHERE e.department_id = d.department_id
                  AND j.job_id = e.job_id
                  AND m.employee_id = e.manager_id)))
  AS XML
  FROM hr.departments d, hr.countries c, hr.locations l
  WHERE department_name = 'Executive'
    AND d.location_id = l.location_id
    AND l.country_id  = c.country_id;

この問合せでは、次のXMLが戻されます。

XML
--------------------------------------------------------------------------------
<Department DepartmentId="90"><Name>Executive</Name><Location><Address>2004
 Charade Rd</Address><City>Seattle</City><State>Washingto
n</State><Zip>98199</Zip><Country>United States of
 America</Country></Location><EmployeeList><Employee
 employeeNumber="101"><FirstNa
me>Neena</FirstName><LastName>Kochhar</LastName><EmailAddress>NKOCHHAR</EmailAdd
ess><PHONE_NUMBER>515.123.4568</PHONE_NUMBER><Start
Date>2005-09-21</StartDate><JobTitle>Administration Vice
 President</JobTitle><Salary>17000</Salary><Manager>Steven King</Manager><Com
mission></Commission></Employee><Employee
 employeeNumber="102"><FirstName>Lex</FirstName><LastName>De
 Haan</LastName><EmailAddress>L
DEHAAN</EmailAddress><PHONE_NUMBER>515.123.4569</PHONE
NUMBER><StartDate>2001-01-13</StartDate><JobTitle>Administration Vice Presiden
t</JobTitle><Salary>17000</Salary><Manager>Steven
 King</Manager><Commission></Commission></Employee></EmployeeList></Department>

この問合せは、departments表の行ごとに要素Departmentを生成します。

  • Department要素には、属性DepartmentIDが含まれます。DepartmentIDの値はdepartment_ed列から生成されます。このDepartment要素には、サブ要素のNameLocationおよびEmployeeListも含まれます。

  • Name要素に関連付けられたテキスト・ノードは、departments表のname列から生成されます。

  • Location要素には、子要素AddressCityStateZipおよびCountryが含まれます。これらの要素は、locations表およびcountries表の列からフォレスト、つまり名前付き要素を作成することで構成されます。列内の値は、名前付き要素に対するテキスト・ノードになります。

  • EmployeeList要素には、Employee要素の集計が含まれます。EmployeeList要素のコンテンツは、現在の部門に対応するemployees表の一連の行を戻す副問合せによって作成されます。各Employee要素には、従業員に関する情報が含まれます。各Employee要素のコンテンツおよび属性は、表employeesおよびjobsから取得されます。

SQL/XML関数で生成される出力は、通常はフォーマット出力ではありません。ただし、関数XMLSerializeは例外で、XMLSerializeを使用してフォーマット出力します。このため、他のSQL/XML関数で必要な出力を生成するときに、(1)完全なDOMが作成されるのを回避し、(2)生成される文書のサイズを縮小できます。ほとんどのアプリケーションでは、このように大半のSQL/XML関数でフォーマット出力が生成されなくても問題ありません。ただし、生成された出力を手動で検証することは困難になります。

例3-42 従来のリレーショナル表のXMLTypeビューの作成

CREATE OR REPLACE VIEW department_xml OF XMLType
  WITH OBJECT ID (substr(
                    XMLCast(
                      XMLQuery('$p/Department/Name'
                               PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
                      AS VARCHAR2(30)),
                    1,
                    128))
  AS
  SELECT XMLElement(
           "Department",
           XMLAttributes(d.department_id AS "DepartmentId"),
           XMLForest(d.department_name AS "Name"),
           XMLElement("Location", XMLForest(street_address AS "Address",
                                            city AS "City",
                                            state_province AS "State",
                                            postal_code AS "Zip",
                                            country_name AS "Country")),
           XMLElement(
             "EmployeeList",
             (SELECT XMLAgg(
                       XMLElement(
                          "Employee",
                          XMLAttributes(e.employee_id AS "employeeNumber"),
                          XMLForest(e.first_name AS "FirstName",
                                    e.last_name AS "LastName",
                                    e.email AS "EmailAddress",
                                    e.phone_number AS "PHONE_NUMBER",
                                    e.hire_date AS "StartDate",
                                    j.job_title AS "JobTitle",
                                    e.salary AS "Salary",
                                    m.first_name || ' ' ||
                                    m.last_name AS "Manager"),
                          XMLElement("Commission", e.commission_pct)))
                FROM hr.employees e, hr.employees m, hr.jobs j
                WHERE e.department_id = d.department_id
                  AND j.job_id = e.job_id
                  AND m.employee_id = e.manager_id))).extract('/*')
    AS XML
    FROM hr.departments d, hr.countries c, hr.locations l
    WHERE d.location_id = l.location_id
      AND l.country_id  = c.country_id;

View created.

XMLTypeビューによって、リレーショナル・データをXMLコンテンツとして永続的に保持できます。また、XMLTypeビューの行は、Oracle XML DBリポジトリに文書として永続的に保持できます。例3-43に示すように、XMLTypeビューのコンテンツは問合せが可能です。

例3-43は、XMLTypeビューに対する簡単な問合せを示しています。SQL/XML関数XMLExistsに渡されるXPath式によって、結果セットは、Executive部門の情報が含まれたノードに制限されます。結果は、わかりやすくするためフォーマット出力しています。

例3-43 XMLTypeビューの問合せ

SELECT OBJECT_VALUE FROM department_xml
  WHERE XMLExists('$p/Department[Name="Executive"]' PASSING OBJECT_VALUE AS "p");
 
OBJECT_VALUE
------------------------------------------------
<Department DepartmentId="90">
  <Name>Executive</Name>
  <Location>
    <Address>2004 Charade Rd</Address>
    <City>Seattle</City>
    <State>Washington</State>
    <Zip>98199</Zip>
    <Country>United States of America</Country>
  </Location>
  <EmployeeList>
    <Employee employeeNumber="101">
      <FirstName>Neena</FirstName>
      <LastName>Kochhar</LastName>
      <EmailAddress>NKOCHHAR</EmailAddress>
      <PHONE_NUMBER>515.123.4568</PHONE_NUMBER>
      <StartDate>2005-09-21</StartDate>
      <JobTitle>Administration Vice President</JobTitle>
      <Salary>17000</Salary>
      <Manager>Steven King</Manager>
      <Commission/>
    </Employee>
    <Employee employeeNumber="102">
      <FirstName>Lex</FirstName>
      <LastName>De Haan</LastName>
      <EmailAddress>LDEHAAN</EmailAddress>
      <PHONE_NUMBER>515.123.4569</PHONE_NUMBER>
      <StartDate>2001-01-13</StartDate>
      <JobTitle>Administration Vice President</JobTitle>
      <Salary>17000</Salary>
      <Manager>Steven King</Manager>
      <Commission/>
    </Employee>
  </EmployeeList>
</Department>
 
1 row selected.

次の実行計画の出力に示すとおり、Oracle XML DBには、XMLExists式のXPath式の引数を、基礎となるリレーショナル表のSELECT文に正しくリライトする機能があります。

SELECT OBJECT_VALUE FROM department_xml
  WHERE XMLExists('$p/Department[Name="Executive"]' PASSING OBJECT_VALUE AS "p");

PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------
Plan hash value: 2414180351

----------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                   |     1 |    80 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE                |                   |     1 |   115 |            |          |
|*  2 |   HASH JOIN                    |                   |    10 |  1150 |     7  (15)| 00:00:01 |
|*  3 |    HASH JOIN                   |                   |    10 |   960 |     5  (20)| 00:00:01 |
|   4 |     TABLE ACCESS BY INDEX ROWID| EMPLOYEES         |    10 |   690 |     2   (0)| 00:00:01 |
|*  5 |      INDEX RANGE SCAN          | EMP_DEPARTMENT_IX |    10 |       |     1   (0)| 00:00:01 |
|   6 |     TABLE ACCESS FULL          | JOBS              |    19 |   513 |     2   (0)| 00:00:01 |
|   7 |    TABLE ACCESS FULL           | EMPLOYEES         |   107 |  2033 |     2   (0)| 00:00:01 |
|   8 |  NESTED LOOPS                  |                   |     1 |    80 |     3   (0)| 00:00:01 |
|   9 |   NESTED LOOPS                 |                   |     1 |    68 |     3   (0)| 00:00:01 |
|* 10 |    TABLE ACCESS FULL           | DEPARTMENTS       |     1 |    19 |     2   (0)| 00:00:01 |
|  11 |    TABLE ACCESS BY INDEX ROWID | LOCATIONS         |     1 |    49 |     1   (0)| 00:00:01 |
|* 12 |     INDEX UNIQUE SCAN          | LOC_ID_PK         |     1 |       |     0   (0)| 00:00:01 |
|* 13 |   INDEX UNIQUE SCAN            | COUNTRY_C_ID_PK   |     1 |    12 |     0   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("M"."EMPLOYEE_ID"="E"."MANAGER_ID")
   3 - access("J"."JOB_ID"="E"."JOB_ID")
   5 - access("E"."DEPARTMENT_ID"=:B1)
  10 - filter("D"."DEPARTMENT_NAME"='Executive')
  12 - access("D"."LOCATION_ID"="L"."LOCATION_ID")
  13 - access("L"."COUNTRY_ID"="C"."COUNTRY_ID")
 
30 rows selected.

注意:

XMLTypeビューで操作するXML式でのXPathリライトは、XPath式で参照するノードが、SQL関数XMLAggを使用して作成された要素の子孫でない場合にのみサポートされます。

DBURITYPEを使用した、リレーショナル・データからのXMLデータの生成

SQL関数DBURITypeを使用して、リレーショナル・データからXMLを生成することもできます。関数DBURITypeは、指定された表またはビューの1つ以上の行を単一のXML文書として公開します。ルート要素の名前は、表またはビューの名前から導出されます。ルート要素には、一連のROW要素が含まれます。表またはビュー内の行ごとにROW要素が1つずつあります。各ROW要素の子は、表またはビューの列から導出されます。各子要素には、指定された行の列の値を持つテキスト・ノードが含まれます。

例3-44に、SQL関数DBURITypeを使用して、データベース・スキーマHRの表departmentsのコンテンツにアクセスする方法を示します。メソッドgetXML()を使用して結果の文書をXMLTypeインスタンスとして戻します。

例3-44 DBURITypeおよびgetXML()を使用したリレーショナル表からのXMLデータの生成

SELECT DBURIType('/HR/DEPARTMENTS').getXML() FROM DUAL;
 
DBURITYPE('/HR/DEPARTMENTS').GETXML()
------------------------------------------------------
<?xml version="1.0"?>
<DEPARTMENTS>
 <ROW>
  <DEPARTMENT_ID>10</DEPARTMENT_ID>
  <DEPARTMENT_NAME>Administration</DEPARTMENT_NAME>
  <MANAGER_ID>200</MANAGER_ID>
  <LOCATION_ID>1700</LOCATION_ID>
 </ROW>
...
 <ROW>
  <DEPARTMENT_ID>20</DEPARTMENT_ID>
  <DEPARTMENT_NAME>Marketing</DEPARTMENT_NAME>
  <MANAGER_ID>201</MANAGER_ID>
  <LOCATION_ID>1800</LOCATION_ID>
 </ROW>
</DEPARTMENTS>

例3-45では、XPath述語を使用して、DBURITypeによって生成されるXML文書に含める行を制限する方法を示します。この例のXPath式によって、値が10DEPARTMENT_ID列のみにXML文書が制限されます。

例3-45 XPath述語を使用した行の制限

SELECT DBURIType('/HR/DEPARTMENTS/ROW[DEPARTMENT_ID="10"]').getXML()
  FROM DUAL;
 
DBURITYPE('/HR/DEPARTMENTS/ROW[DEPARTMENT_ID="10"]').GETXML()
------------------------------------------------------------------
<?xml version="1.0"?>
 <ROW>
  <DEPARTMENT_ID>10</DEPARTMENT_ID>
  <DEPARTMENT_NAME>Administration</DEPARTMENT_NAME>
  <MANAGER_ID>200</MANAGER_ID>
  <LOCATION_ID>1700</LOCATION_ID>
 </ROW>

1 row selected.

SQL関数DBURITypeを使用すると、リレーショナル表の一部または全部の行を1つ以上のXML文書として簡単に公開できます。関数DBURITypeに渡されるURLを拡張してビューまたは表から単一列を戻すことができますが、その場合、URLには、ターゲットの表またはビューの単一行を識別する述語も含まれる必要があります。

例3-46に、これを示します。述語[DEPARTMENT_ID="10"]句は、department_id列に値10が含まれるdepartments行について、department_name列の値を問合せで戻します。

例3-46 XPath述語を使用した行と列の制限

SELECT DBURIType(
         '/HR/DEPARTMENTS/ROW[DEPARTMENT_ID="10"]/DEPARTMENT_NAME').getXML()
  FROM DUAL;
 
DBURITYPE('/HR/DEPARTMENTS/ROW[DEPARTMENT_ID="10"]/DEPARTMENT_NAME').GETXML()
-----------------------------------------------------------------------------
<?xml version="1.0"?>
 <DEPARTMENT_NAME>Administration</DEPARTMENT_NAME>
 
1 row selected.

SQL関数DBURITypeは、次の点でSQL/XML関数よりも柔軟性が低くなっています。

  • DBURITypeでは、生成された文書の形式を制御できません。

  • データは、単一の表またはビューからのみ生成できます。

  • 生成される文書は、1つ以上のROW要素で構成されます。各ROW要素には、ターゲット表の列ごとの子が含まれます。

  • 子要素の名前は、列の名前から導出されます。

XML要素の名前を制御する場合、複数の表からの列を含める場合、または生成される文書に含める表の列を制御する場合は、必要な列を単一行として公開するリレーショナル・ビューを作成してから、関数DBURITypeを使用して、そのビューのコンテンツからXML文書を生成します。

XSL変換とOracle XML DB

W3CのXSLT勧告は、XML文書の形式を別の形式に変換する方法を指定するためのXML言語を定義します。変換には、1つのXML Schemaから別のXML Schemaへのマッピング、またはXMLからHTMLやWMLなどの他の形式へのマッピングが含まれる場合があります。


関連項目:

XSLT標準の詳細は、http://www.w3.org/XML/Schemaを参照してください。

XSL変換は、通常、必要なメモリー量および処理量の面からコストがかかります。文書の様々な部分へのランダムなアクセスが可能になるように、ソース・ドキュメントとスタイルシートの両方を解析してメモリー構造にロードする必要があります。ほとんどのXSLプロセッサは、DOMを使用して両方の文書の動的メモリー表現を提供します。次に、XSLプロセッサは、スタイルシートをソース・ドキュメントに適用して、3番目の文書を生成します。

Oracle XML DBには、XSL変換をデータベース内で実行できるXSLTプロセッサが含まれています。この方法では、Oracle XML DBで、変換の実行に必要なメモリーを大幅に削減する、XML特有のメモリー最適化を提供できます。さらに、文書の解析に関連するオーバーヘッドも削減できます。ただし、これらの最適化は、変換対象のソースがスキーマに基づくXML文書である場合にのみ使用できます。

Oracle XMLでは、次の3つの方法でXSLプロセッサを起動できます。

  • SQL関数XMLtransform

  • XMLTypeメソッドtransform()

  • PL/SQLパッケージDBMS_XSLPROCESSOR

これらの各XML変換方法では、ソースXML文書およびXSLスタイルシートを、XMLTypeインスタンスの形式で入力として受け取ります。SQL関数XMLtransformおよびXMLTypeメソッドtransform()では、変換の結果としてXML文書または非XML文書(HTMLなど)が発生します。しかし、PL/SQLパッケージDBMS_XSLPROCESSORでは、変換の結果は有効なXML文書であることが求められます。パッケージDBMS_XSLPROCESSORを使用した変換によって生成されるHTMLは、XHTML(つまり、有効なXMLと有効なHTML)である必要があります。

例3-47は、XSLTスタイルシートPurchaseOrder.xsl一部を示しています。完全なスタイルシートは、「XSLスタイルシートの例: PurchaseOrder.xsl」に記載されています。

例3-47 XSLTスタイルシートの例: PurchaseOrder.xsl

<?xml version="1.0" encoding="WINDOWS-1252"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xdb="http://xmlns.oracle.com/xdb" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <xsl:template match="/">
    <html>
      <head/>
      <body bgcolor="#003333" text="#FFFFCC" link="#FFCC00" vlink="#66CC99" alink="#669999">
        <FONT FACE="Arial, Helvetica, sans-serif">
          <xsl:for-each select="PurchaseOrder"/>
          <xsl:for-each select="PurchaseOrder">
            <center>
              <span style="font-family:Arial; font-weight:bold">
                <FONT COLOR="#FF0000">
                  <B>PurchaseOrder </B>
                </FONT>
              </span>
            </center>
            <br/>
            <center>
              <xsl:for-each select="Reference">
                <span style="font-family:Arial; font-weight:bold">
                  <xsl:apply-templates/>
                </span>
              </xsl:for-each>
            </center>
          </xsl:for-each>
          <P>
            <xsl:for-each select="PurchaseOrder">
              <br/>
            </xsl:for-each>
            <P/>
            <P>
              <xsl:for-each select="PurchaseOrder">
                <br/>
              </xsl:for-each>
            </P>
          </P>
          <xsl:for-each select="PurchaseOrder"/>
          <xsl:for-each select="PurchaseOrder">
            <table border="0" width="100%" BGCOLOR="#000000">
              <tbody>
                <tr>
                  <td WIDTH="296">
                    <P>
                      <B>
                        <FONT SIZE="+1" COLOR="#FF0000" FACE="Arial, Helvetica, sans-serif">Internal</FONT>
                      </B>
                    </P>

                    ...

                  </td>
                  <td width="93"/>
                  <td valign="top" WIDTH="340">
                    <B>
                      <FONT COLOR="#FF0000">
                        <FONT SIZE="+1">Ship To</FONT>
                      </FONT>
                    </B>
                    <xsl:for-each select="ShippingInstructions">
                      <xsl:if test="position()=1"/>
                    </xsl:for-each>
                    <xsl:for-each select="ShippingInstructions">
                    </xsl:for-each>
 
                      ...

例3-47のスタイルシートに関して、Oracle XML DB固有のものはありません。スタイルシートは、XMLType表または列に格納でき、Oracle XML DBリポジトリ内にXML Schemaに基づかないXMLデータとしても格納できます。

変換をデータベース内部で実行することによって、Oracle XML DBでは、メモリー使用量、I/O操作およびネットワーク通信量などの機能を最適化できます。これらの最適化は、変換がソース文書内のノードの小さいサブセットで実行される場合に特に有効です。

従来のXSLプロセッサでは、XSL処理を開始する前に、ソース・ドキュメント全体を解析してメモリーにロードする必要があります。この処理には、多くのメモリーおよびプロセッサが必要です。この処理は、文書の小規模な部分を処理する場合にのみ非効率になります。

Oracle XML DBがスキーマに基づくXML文書でXSL変換を実行する場合、処理の開始前に文書を解析する必要はありません。遅延ロードされた仮想DOMの場合は、ノードへのアクセス時にコンテンツをディスクから直接ロードするため、文書の解析が不要になります。また、遅延ロードでは、文書の処理対象部分のみがメモリーにロードされるため、変換の実行に必要なメモリーの量も削減されます。

例3-48では、SQL関数XMLtransformを使用して、XMLType表に格納された文書にXSLスタイルシートを適用し、HTMLコードを生成する方法を示します。SQL関数XDBURITypeは、XSLスタイルシートをOracle XML DBリポジトリから読み取ります。

簡略にするため、例3-48では変換結果の一部のみを示しています。省略した部分は、省略記号(. . .)で示しています。図3-7に、変換された結果がWebブラウザでどのように表示されるかを示します。

例3-48 TRANSFORMを使用したスタイルシートの適用

SELECT
  XMLtransform(
    OBJECT_VALUE, 
    XDBURIType('/source/schemas/poSource/xsl/purchaseOrder.xsl').getXML())
  FROM purchaseorder
  WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
                  PASSING OBJECT_VALUE AS "p");
 
XMLTRANSFORM(OBJECT_VALUE, XDBURITYPE('/SOURCE/SCHEMAS/POSOURCE/XSL/PURCHASEORDER.XSL').GET
---------------------------------------------------------------------------------------------
<html xmlns:xdb="http://xmlns.oracle.com/xdb"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <head/>
  <body bgcolor="#003333" text="#FFFFCC" link="#FFCC00" vlink="#66CC99" alink="#669999">
    <FONT FACE="Arial, Helvetica, sans-serif">
      <center>
        <span style="font-family:Arial; font-weight:bold">
          <FONT COLOR="#FF0000">
            <B>PurchaseOrder </B>
          </FONT>
        </span>
      </center>
      <br/>
      <center>
        <span style="font-family:Arial; font-weight:bold">SBELL-2002100912333601PDT</span>
      </center>
      <P>
        <br/>
        <P/>
        <P>
          <br/>
        </P>
      </P>
      <table border="0" width="100%" BGCOLOR="#000000">
        <tbody>
          <tr>
            <td WIDTH="296">
              <P>
                <B>
                  <FONT SIZE="+1" COLOR="#FF0000" FACE="Arial, Helvetica,
                        sans-serif">Internal</FONT>
                </B>
              </P>
              <table border="0" width="98%" BGCOLOR="#000099">
                                                     . . .
              </table>
            </td>
            <td width="93">
            </td>
            <td valign="top" WIDTH="340">
              <B>
                <FONT COLOR="#FF0000">
                  <FONT SIZE="+1">Ship To</FONT>
                </FONT>
              </B>
              <table border="0" BGCOLOR="#999900">
                . . .
              </table>
            </td>
          </tr>
        </tbody>
      </table>
      <br/>
      <B>
        <FONT COLOR="#FF0000" SIZE="+1">Items:</FONT>
      </B>
      <br/>
      <br/>
      <table border="0">
        . . .
      </table>
    </FONT>
  </body>
</html>
 
1 row selected.

Oracle XML DBリポジトリの使用

Oracle XML DBリポジトリを使用すると、XMLコンテンツをファイル/フォルダ隠喩を使用して編成できます。これによって、URLを使用して、データベースに格納されたXML文書を一意に識別できます。これまでURLやXPath式などの構造体を使用してコンテンツを識別してきたXML開発者は、この方法の使用を検討できます。

Oracle XML DBリポジトリは、DAV標準に基づいてモデル化されています。DAV標準では、WebDAVサーバーで管理されるファイルやフォルダを示すためにリソースという用語が使用されます。リソースは、メタデータとコンテンツの組合せで構成されます。DAV仕様には、リソースごとにWebDAVサーバーが管理する一連の(システム定義の)メタデータ・プロパティ、およびDAVサーバーやDAV対応クライアントでメタデータを交換するために使用する一連のXML文書が定義されています。

Oracle XML DBリポジトリでは、あらゆる種類のコンテンツを管理できますが、コンテンツがXMLであるリソースを管理するための特別な機能と最適化機能が用意されています。

Oracle XML DBリポジトリのインストールおよび削除

Oracle XML DBリポジトリで管理されるすべてのメタデータおよびコンテンツは、一連の表を使用して、データベース・スキーマ(ユーザー・アカウント)XDBが所有するデータベース・スキーマに格納されます。ユーザーXDBはロックされたアカウントで、DBCAを使用するか、またはスクリプトcatqm.sqlを実行してインストールされます。スクリプトcatqm.sqlは、ディレクトリORACLE_HOME/rdbms/adminにあります。リポジトリは、DBCAを使用するか、またはスクリプトcatnoqm.sqlを実行して削除できます。catnoqm.sqlを実行すると、Oracle XML DBリポジトリに格納されたすべてのコンテンツが削除され、登録済のXML Schemaに関連するXMLType表または列が無効になるため、このスクリプトを実行するときは十分な注意が必要です。


関連項目:

データベース・スキーマXDBの詳細は、『Oracle Database 2日でセキュリティ・ガイド』を参照してください。

Oracle XML DBで提供される名前レベル・ロック

リレーショナル・データベースを使用して階層フォルダ構造を保持する場合、フォルダに対して項目を追加または削除するときに高度な同時実行性を保証することは重要な問題です。従来のファイル・システムでは、トランザクションの概念はありません。各操作(ファイルの追加、サブフォルダの作成、ファイル名の変更、ファイルの削除など)は、基本トランザクションとして処理されます。操作が完了すると、ファイル・システムのすべてのユーザーに対して変更がすぐに反映されます。


注意:

データベースによって適用されるトランザクション・セマンティクスの結果として、SQL文を使用して作成されたフォルダは、トランザクションがコミットされるまで他のデータベース・ユーザーから参照されません。Oracle XML DBリポジトリへの同時アクセスは、Oracle Databaseの同時実行性の制御に使用されるのと同じメカニズムを使用して制御されます。リポジトリのOracle Databaseとの統合により、XMLコンテンツに対する強力な管理オプションが提供されます。

Oracle XML DBリポジトリの主要なメリットの1つは、論理トランザクションでのリポジトリ操作でSQLを使用できることです。アプリケーションでは、1つ以上のフォルダを更新する操作が含まれた、長時間実行するトランザクションを作成できます。この場合、更新されたフォルダまたはディレクトリ・ツリーに排他ロックを設定する従来のロック方針では、同時実行性に関する重大な問題がすぐに発生します。

Oracle XML DBでは、フォルダ・レベル・ロックではなく名前レベル・ロックを提供して、これを解決します。サブフォルダまたはファイルの作成、名前の変更、移動、削除などのリポジトリ操作では、ターゲット・フォルダに対する排他書込みロックの付与は必要はありません。リポジトリは、フォルダ自体ではなくフォルダ内の名前をロックして、フォルダに対する同時操作を管理します。名前および変更タイプは、キューに入れられます。

トランザクションがコミットされた場合にのみ、フォルダがロックされてそのコンテンツが変更されます。したがって、Oracle XML DBでは、1つのフォルダのコンテンツに対して複数のアプリケーションが同時に更新を実行できます。また、キューを使用すると、2つのアプリケーションによる同じ名前のオブジェクトの作成を回避できるため、フォルダの同時実行性を管理できます。

同じトランザクションで1つのフォルダに対して複数の変更が行われる場合は、コミット時までフォルダの変更をキューに入れて、I/Oを最小限にすることもできます。

これは、短時間の間に複数のアプリケーションが同じディレクトリ内にファイルを生成する場合に役立ちます。たとえば、トレース・ファイルやログ・ファイルを生成する場合、印刷または電子メール配信用にスプール・ディレクトリを保持する場合などです。

プロトコルまたはSQLを使用した、リポジトリのコンテンツへのアクセスおよび処理

Oracle XML DBリポジトリに格納されたコンテンツは、次の方法で操作できます。

  • HTTP(S)、WebDAV、FTPなどの業界標準のプロトコルを使用して、挿入、更新、削除など文書レベルの操作を実行します。

  • SQLを使用して、表レベルまたは行レベルでOracle XML DBリポジトリに直接アクセスします。

  • Oracle XML DB Content Connectorを使用します(第31章「Oracle XML DB Content Connectorの使用」を参照)。

標準プロトコルを使用したデータベース・コンテンツの格納と取出し

Oracle XML DBは、HTTP(S)、WebDAV、FTPなどの業界標準のインターネット・プロトコルをサポートしています。プロトコルのサポートとURLベースのアクセスを組み合せることによって、Windows Explorer、Microsoft Word、XMLSpyなどの標準的なデスクトップ・アプリケーションから、Oracle Databaseに格納されたコンテンツに対して挿入、取出し、更新および削除を行うことができます。

図3-4に、Windows Explorerを使用して、フォルダをローカル・ハード・ドライブからOracle Databaseに挿入する操作を示します。Windows Explorerは、WebDAVプロトコルをサポートしています。WebDAVはHTTP標準の拡張で、HTTPサーバーがファイル・サーバーとして機能できる動詞が追加されています。

Windows Explorerのコピー操作やFTPの入力コマンドを使用して、多数の文書をOracle XML DBリポジトリに転送する場合、それぞれのputまたはpostコマンドは、個別の基本操作として扱われます。これにより、ファイル転送のうちのいずれかが失敗してもクライアントに混乱が生じません。また、プロトコルを介して文書に加えられた変更は、リクエストが処理されるとすぐに、他のユーザーも参照できます。

図3-4 Oracle XML DBリポジトリへのファイルのコピー

図3-4の説明が続きます
「図3-4 Oracle XML DBリポジトリへのファイルのコピー」の説明

FTPを使用したOracle XML DBへのコンテンツのアップロード

例3-49では、標準のコマンドラインFTPツールで文書をOracle XML DBリポジトリにロードするときに発行されるコマンドと、生成された出力を示します。

例3-49 FTPを使用したリポジトリへのコンテンツのアップロード

$ ftp mdrake-sun 2100
Connected to mdrake-sun.
220 mdrake-sun FTP Server (Oracle XML DB/Oracle Database 10g Enterprise Edition
Release 10.1.0.1.0 - Beta) ready.
Name (mdrake-sun:oracle10): QUINE
331 Password required for QUINE
Password: password
230 QUINE logged in
ftp> cd /source/schemas
250 CWD Command successful
ftp> mkdir PurchaseOrders
257 MKD Command successful
ftp> cd PurchaseOrders
250 CWD Command successful
ftp> mkdir 2002
257 MKD Command successful
ftp> cd 2002
250 CWD Command successful
ftp> mkdir "Apr"
257 MKD Command successful
ftp> put "Apr/AMCEWEN-20021009123336171PDT.xml"
"Apr/AMCEWEN-20021009123336171PDT.xml"
200 PORT Command successful
150 ASCII Data Connection
226 ASCII Transfer Complete
local: Apr/AMCEWEN-20021009123336171PDT.xml remote:
Apr/AMCEWEN-20021009123336171PDT.xml
4718 bytes sent in 0.0017 seconds (2683.41 Kbytes/s)
ftp> put "Apr/AMCEWEN-20021009123336271PDT.xml"
"Apr/AMCEWEN-20021009123336271PDT.xml"
200 PORT Command successful
150 ASCII Data Connection
226 ASCII Transfer Complete
local: Apr/AMCEWEN-20021009123336271PDT.xml remote:
Apr/AMCEWEN-20021009123336271PDT.xml
4800 bytes sent in 0.0014 seconds (3357.81 Kbytes/s)
.....
ftp> cd "Apr"
250 CWD Command successful
ftp> ls -l
200 PORT Command successful
150 ASCII Data Connection
-rw-r--r1 QUINE oracle 0 JUN 24 15:41 AMCEWEN-20021009123336171PDT.xml
-rw-r--r1 QUINE oracle 0 JUN 24 15:41 AMCEWEN-20021009123336271PDT.xml
-rw-r--r1 QUINE oracle 0 JUN 24 15:41 EABEL-20021009123336251PDT.xml
-rw-r--r1 QUINE oracle 0 JUN 24 15:41 PTUCKER-20021009123336191PDT.xml
-rw-r--r1 QUINE oracle 0 JUN 24 15:41 PTUCKER-20021009123336291PDT.xml
-rw-r--r1 QUINE oracle 0 JUN 24 15:41 SBELL-20021009123336231PDT.xml
-rw-r--r1 QUINE oracle 0 JUN 24 15:41 SBELL-20021009123336331PDT.xml
-rw-r--r1 QUINE oracle 0 JUN 24 15:41 SKING-20021009123336321PDT.xml
-rw-r--r1 QUINE oracle 0 JUN 24 15:41 SMCCAIN-20021009123336151PDT.xml
-rw-r--r1 QUINE oracle 0 JUN 24 15:41 SMCCAIN-20021009123336341PDT.xml
-rw-r--r1 QUINE oracle 0 JUN 24 15:41 VJONES-20021009123336301PDT.xml
226 ASCII Transfer Complete
remote: -l
959 bytes received in 0.0027 seconds (349.45 Kbytes/s)
ftp> cd ".."
250 CWD Command successful
....
ftp> quit
221 QUIT Goodbye.
$

図3-4および例3-49で示されている要点は、Windows ExplorerおよびFTPツールのいずれもがOracle XML DBの操作を認識していないことです。ツールおよびOracle XML DBの両方がオープン・インターネット・プロトコルをサポートしているため、最初から相互に使用できます。

WebDAVまたはFTPプロトコルを認識するツールを使用すると、Oracle XML DBリポジトリで管理されるコンテンツを作成できます。クライアントまたは中間層に追加のソフトウェアをインストールする必要はありません。

Windows ExplorerやFTPなどのツールを使用してフォルダのコンテンツを表示すると、そのフォルダに格納されたXML Schemaに基づくXML文書のサイズは0(ゼロ)バイトと表示されます。このように設計されているのは、次の2つの理由からです。

  • 文書のどのサイズを表示する必要があるかが明確でありません。文書に関連するサイズには、文書を出力して生成されたCLOBインスタンスのサイズ、文書をデータベース内に永続的に保持するために使用するオブジェクトの格納に必要なバイト数などがあります。

  • 選択された定義に関係なく、この情報を計算して保持するにはコストがかかります。

図3-5に、Internet ExplorerでURLおよびHTTPプロトコルを使用して、データベースに格納されたXML文書を表示する操作を示します。

図3-5 HTTPとURLを使用したパスベースのアクセス

図3-5の説明が続きます
「図3-5 HTTPとURLを使用したパスベースのアクセス」の説明

プログラムを使用したOracle XML DBリポジトリへのアクセス

Oracle XML DBリポジトリは、SQLから直接アクセスして更新できます。そのため、SQLを使用してOracle Databaseと対話できるアプリケーションまたはプログラミング言語からも、リポジトリに格納されたコンテンツにアクセスして更新できます。Oracle XML DBには、プログラムによるリソースの作成、変更および削除を可能にするメソッドが備わったPL/SQLパッケージDBMS_XDBが含まれています。

例3-50に、PL/SQL関数DBMS_XDB.createResourceを使用して簡単なテキスト・ドキュメントのリソースを作成する方法を示します。

例3-50 CREATERESOURCEを使用したテキスト・ドキュメント・リソースの作成

DECLARE
  res BOOLEAN;
BEGIN
  res := DBMS_XDB.createResource('/home/QUINE/NurseryRhyme.txt',
                                 bfilename('XMLDIR', 'tdadxdb-03-01.txt'),
                                 nls_charset_id('AL32UTF8'));
END;
/

リポジトリ内のXMLコンテンツのアクセスおよび更新

この項では、Oracle XML DBリポジトリのコンテンツにアクセスして更新するための機能について説明します。

SQLを使用したXML文書へのアクセス

リポジトリに格納されたコンテンツには、SQLおよびPL/SQLからアクセスして更新できます。このリポジトリの構造は、複合したいくつかの方法で問い合せることができます。たとえば、/home/mystylesheetdir以外の場所にある、拡張子が.xslの文書の数を調べる問合せを発行できます。

また、パスベースのリポジトリ・アクセスとコンテンツ・ベースのアクセスを組み合せることもできます。たとえば、/home/purchaseOrders以外の場所にある、値がKINGのXPath /PurchaseOrder/User/text()で識別されるノードを持つ文書の数を問い合せることができます。

リポジトリを管理するためのすべてのメタデータは、データベース・スキーマ(ユーザー・アカウント)XDBが所有するデータベース・スキーマに格納されます。ユーザーXDBは、Oracle XML DBのインストール時に作成されます。このスキーマの主な表は、XDB$RESOURCEというXMLType表です。この表には、リポジトリ内のリソース(ファイルまたはフォルダ)ごとに1行ずつが含まれます。この表内の文書はリソース・ドキュメントと呼ばれます。Oracle XML DBのリソース・ドキュメントの構造を定義するXML Schemaは、URL http://xmlns.oracle.com/xdb/XDBResource.xsdに登録されています。


関連項目:

データベース・スキーマXDBの詳細は、『Oracle Database 2日でセキュリティ・ガイド』を参照してください。

RESOURCE_VIEWとPATH_VIEWを介して公開されるリポジトリのコンテンツ

XDB$RESOURCEは、SQLプログラマに直接公開されていません。リポジトリのコンテンツは、2つのパブリック・ビュー(RESOURCE_VIEWおよびPATH_VIEW)を介して公開されます。リポジトリに格納された文書のメタデータおよびコンテンツはいずれも、これらのビューを介してアクセスして更新できます。いずれのビューにも仮想列RESが含まれます。パス表記法を使用したSQL文でドキュメントにアクセスして更新するには、RESを使用します。ビューに対する操作では、リポジトリ内の基礎となる表を使用します。

EXISTS_PATHとUNDER_PATHを使用した、WHERE句へのパスベースの述語の追加

Oracle XML DBには、リポジトリ固有のSQL関数としてexists_pathおよびunder_pathという2つの関数があります。これらの関数を使用して、パスベースの述語をSQL文のWHERE句に含めます。SQL操作では、リポジトリのフォルダ階層内におけるコンテンツの場所に基づいてリポジトリのコンテンツを選択できます。階層リポジトリ索引を使用すると、パスベースの問合せが効率的に実行されます。

XML Schemaに基づくXML文書をリポジトリに格納すると、文書のコンテンツはXML Schemaにより識別されるデフォルト表にオブジェクトとして格納されます。リポジトリには、文書に関するメタデータと、コンテンツを含むデフォルト表内の行を識別するポインタ(XMLTypeREF)のみが含まれます。

リポジトリへの非XML文書の格納も可能

別の種類の文書をリポジトリに格納することも可能です。XMLでない、またはXML Schemaに基づかない文書をリポジトリに格納すると、文書のコンテンツは、文書のメタデータとともにLOBに格納されます。

フォルダと文書の作成、削除、名前変更、移動などを実行するためのPL/SQLパッケージ

Oracle XML DBリポジトリはSQLを使用してアクセスおよび更新できるため、PL/SQLプロシージャをコールできるアプリケーションはすべて、このリポジトリを使用できます。すべてのSQLおよびPL/SQLリポジトリ操作はトランザクション型です。リポジトリとそのコンテンツへのアクセスは、標準的なデータベース・セキュリティ制御とリポジトリのアクセス制御リスト(ACL)両方の対象となります。

提供されているPL/SQLパッケージDBMS_XDBDBMS_XDBZおよびDBMS_XDB_VERSIONを使用すると、文書とフォルダの作成、削除および名前変更、フォルダ階層内でのファイルまたはフォルダの移動、ファイルまたはフォルダに対するアクセス権限の設定および変更、バージョニングの開始および管理を実行できます。

例3-51では、PL/SQLパッケージDBMS_XDBを使用して、フォルダ/publicの下位に一連のサブフォルダを作成します。

例3-51 PL/SQLパッケージDBMS_XDBを使用したフォルダの作成

DECLARE
  RESULT BOOLEAN;
BEGIN
  IF (NOT DBMS_XDB.existsResource('/public/mysource')) THEN
     result := DBMS_XDB.createFolder('/public/mysource');
  END IF;
  IF (NOT DBMS_XDB.existsResource('/public/mysource/schemas')) THEN
     result := DBMS_XDB.createFolder('/public/mysource/schemas');
  END IF;
  IF (NOT DBMS_XDB.existsResource('/public/mysource/schemas/poSource')) THEN
     result := DBMS_XDB.createFolder('/public/mysource/schemas/poSource');
  END IF;
  IF (NOT DBMS_XDB.existsResource('/public/mysource/schemas/poSource/xsd')) THEN
     result := DBMS_XDB.createFolder('/public/mysource/schemas/poSource/xsd');
  END IF;
  IF (NOT DBMS_XDB.existsResource('/public/mysource/schemas/poSource/xsl')) THEN
     result := DBMS_XDB.createFolder('/public/mysource/schemas/poSource/xsl');
  END IF;
END;
/

SQLを使用した文書のコンテンツへのアクセス

Oracle XML DBリポジトリに格納された文書のコンテンツには、いくつかの方法でアクセスできます。最も簡単な方法は、XDBURITypeを使用することです。XDBURITypeでは、URLを使用して、アクセスするリソースを指定します。XDBURITypeに渡されるURLは、リポジトリのルートから始まると想定されます。データ型XDBURITypeには、リソースに関連付けることのできる様々な種類のコンテンツにアクセスするためのメソッドgetBLOB()getCLOB()およびgetXML()が用意されています。

例3-52では、XDBURITypeを使用してテキスト・ドキュメントのコンテンツにアクセスする方法を示します。

例3-52 XDBURITYPEを使用したリポジトリ内のテキスト・ドキュメントへのアクセス

SELECT XDBURIType('/home/QUINE/NurseryRhyme.txt').getCLOB() FROM DUAL;
 
XDBURITYPE('/HOME/QUINE/NURSERYRHYME.TXT').GETCLOB()
----------------------------------------------------
Mary had a little lamb
Its fleece was white as snow
and everywhere that Mary went
that lamb was sure to go
 
1 row selected.

文書のコンテンツには、リソース・ドキュメントを使用してもアクセスできます。例3-53では、テキスト・ドキュメントのコンテンツにアクセスする方法を示します。

例3-53 RESOURCE_VIEWを使用したリソース・コンテンツへのアクセス

SELECT CONTENT
  FROM RESOURCE_VIEW,
       XMLTable(XMLNAMESPACES (default 'http://xmlns.oracle.com/xdb/XDBResource.xsd'),
                '/Resource/Contents' PASSING RES
                COLUMNS content CLOB PATH 'text')
  WHERE equals_path(RES, '/home/QUINE/NurseryRhyme.txt') = 1;
 
CONTENT
-------
Mary had a little lamb
Its fleece was white as snow
and everywhere that Mary went
that lamb was sure to go
 
1 row selected.

XML Schemaに基づくXML文書とXML Schemaに基づかないXML文書のコンテンツにも、リソースを使用してアクセスできます。例3-54では、リソース・ドキュメントのノードとXML文書のノードが含まれたXPath式、およびリソースを使用して、PurchaseOrder文書のコンテンツにアクセスする方法を示します。

例3-54 リソースと名前空間接頭辞を使用したXML文書へのアクセス

SELECT des.description
  FROM RESOURCE_VIEW rv,
       XMLTable(XMLNAMESPACES ('http://xmlns.oracle.com/xdb/XDBResource.xsd' AS "r"),
                '/r:Resource/r:Contents/PurchaseOrder/LineItems/LineItem'
                PASSING rv.RES
                COLUMNS description VARCHAR2(256) PATH 'Description') des
  WHERE 
    equals_path(rv.RES, '/home/QUINE/PurchaseOrders/2002/Mar/SBELL-2002100912333601PDT.xml') = 1;

DES.DESCRIPTION
---------------------------------
A Night to Remember
The Unbearable Lightness Of Being
The Wizard of Oz
 
3 rows selected.

例3-54では、名前空間接頭辞rを使用し、リソースの名前空間のメンバーであるノードをXPath式から識別しています。名前空間接頭辞rは、SQL/XML関数XMLTableXMLNAMESPACES句を使用して定義されます。発注書XML Schemaで名前空間が定義されておらず、名前空間接頭辞をPurchaseOrder文書のノードに適用できないため、ここでは名前空間の宣言が必要になります。


関連項目:

XMLTableXMLNAMESPACES句の詳細は、第5章「Oracle XML DBでのXQueryの使用」を参照してください。

XML Schemaに基づく文書のコンテンツへのアクセス

XML Schemaに基づくXML文書のコンテンツにアクセスするには、次の2つの方法があります。

  • XML Schemaに基づかないXML文書の場合と同様に、リソース・ドキュメントを使用してアクセスします。この方法では、RESOURCE_VIEWを使用して、XML Schemaに基づく様々な種類のXML文書を1つのSQL文で問い合せることができます。

  • XML SchemaをOracle XML DBに登録したときに定義したデフォルト表の行としてアクセスします。

結合でXMLRef要素を使用した、リソース・コンテンツへのアクセス

リソース・ドキュメントのXMLRef要素は、SQL文で単一の操作の一部としてメタデータおよびコンテンツにアクセスまたは更新するときに必要な結合キーを提供します。

次の問合せでは、要素XMLRefの値に基づく結合を使用して、リソース・コンテンツにアクセスします。

例3-55では、Oracle XML DBリポジトリのパスに基づいて、defaultTableの行を検索します。SQL関数refは、リソース・ドキュメントRES内のXMLRef要素の値に基づいて、デフォルト表内のターゲットの行を検索します。

例3-55 SQL関数REFおよび要素XMLRefを使用した、リポジトリのリソース・データの問合せ

SELECT des.description
  FROM RESOURCE_VIEW rv,
       purchaseorder p,
       XMLTable('$p/PurchaseOrder/LineItems/LineItem' PASSING p.OBJECT_VALUE AS "p"
                COLUMNS description VARCHAR2(256) PATH 'Description') des
  WHERE equals_path(rv.RES, '/home/QUINE/PurchaseOrders/2002/Mar/SBELL-2002100912333601PDT.xml')
        = 1
    AND ref(p) = XMLCast(XMLQuery('declare default element namespace
                                  "http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :)
                                  fn:data(/Resource/XMLRef)' PASSING rv.RES RETURNING CONTENT)
                         AS REF XMLType);
 
DES.DESCRIPTION
---------------------------------
A Night to Remember
The Unbearable Lightness Of Being
The Wizard of Oz
 
3 rows selected.

例3-56では、メタデータ、パスおよびコンテンツに基づいて、XML文書からフラグメントを選択する方法を示します。この問合せは、/home/QUINE/PurchaseOrders/2002/Marの下にあり、部品番号715515009058の発注が含まれる文書に対して、要素Referenceの値を戻します。

例3-56 メタデータ、パスおよびコンテンツに基づくXML文書のフラグメントの選択

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference'
                        PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
               AS VARCHAR2(30))
  FROM RESOURCE_VIEW rv, purchaseorder po
  WHERE under_path(rv.RES, '/home/QUINE/PurchaseOrders/2002/Mar') = 1
    AND ref(po) = XMLCast(
                    XMLQuery('declare default element namespace
                              "http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :)
                              fn:data(/Resource/XMLRef)'
                             PASSING rv.RES RETURNING CONTENT)
                          AS REF XMLType)
    AND XMLExists('$p/PurchaseOrder/LineItems/LineItem/Part[@Id="715515009058"]'
                  PASSING po.OBJECT_VALUE AS "p");

XMLCAST(XMLQUERY('$P/PURCHASEO
------------------------------
CJOHNSON-20021009123335851PDT
LSMITH-2002100912333661PDT
SBELL-2002100912333601PDT
 
3 rows selected.

通常、XML Schemaに基づくXML文書のコンテンツにアクセスするときは、RESOURCE_VIEWまたはPATH_VIEWを単独で使用するよりも、RESOURCE_VIEWまたはPATH_VIEWをデフォルト表と結合して使用した方が効率的です。リソース・ドキュメントとデフォルト表を明示的に結合することによって、Oracle XML DBは、SQL文が1種類のXML文書に対してのみ機能することを認識します。したがって、XPathのリライトを使用すれば、デフォルト表およびリソースに対する操作を最適化できます。

リポジトリに格納された文書のコンテンツの更新

Oracle XML DBリポジトリに格納された文書のコンテンツは、プロトコルまたはSQLを使用して更新できます。

プロトコルを使用したリポジトリのコンテンツの更新

最も一般的なコンテンツ作成ツールは、HTTP、FTPおよびWebDAVプロトコルをサポートしています。このようなコンテンツ作成ツールでは、URLおよびHTTP動詞getを使用して文書のコンテンツにアクセスし、HTTP動詞putを使用してその文書のコンテンツを保存できます。したがって、適切なアクセス権限が付与されている場合、Oracle XML DBリポジトリに格納されたコンテンツにアクセスして編集するには、URLのみが必要です。

図3-6に、Microsoft WordのWebDAVサポートを使用して、Oracle XML DBリポジトリに格納された文書をMicrosoft Wordで更新および編集する方法を示します。

図3-6 Microsoft Wordを使用した、Oracle XML DBに格納されたコンテンツの更新および編集

図3-6の説明が続きます
「図3-6 Microsoft Wordを使用した、Oracle XML DBに格納されたコンテンツの更新および編集」の説明

Microsoft Wordなどの編集アプリケーションを使用してOracle XML DBに格納されたXML文書を更新すると、データベースは、文書の新しいコンテンツを含む入力ストリームを受け取ります。ただし、Wordなどのアプリケーションでは、Oracle XML DBは文書がどのように変更されたかを識別できません。そのため、部分的な変更は不可能です。文書全体を再度解析し、元の文書から導出されたすべてのオブジェクトを、新しいコンテンツから導出されたオブジェクトに置き換える必要があります。

SQLを使用したリポジトリのコンテンツの更新

updateXMLなどのSQL関数を使用すると、Oracle XML DBリポジトリに格納された文書のコンテンツを更新できます。文書のコンテンツを変更するには、リソース・ドキュメントまたは文書のコンテンツを保持するデフォルト表を更新します。

例3-57では、リソース・ドキュメントでSQL UPDATE文およびSQL関数updateXMLを使用して、簡単なテキスト・ドキュメントのコンテンツを更新する方法を示します。XPath式が更新操作のターゲットとしてupdateXMLに渡され、要素/Resource/Contents/textに属するテキスト・ノードが識別されます。

例3-57 リソースでUPDATEとUPDATEXMLを使用したドキュメントの更新

DECLARE
  file         BFILE;
  contents     CLOB;
  dest_offset  NUMBER := 1;
  src_offset   NUMBER := 1;
  lang_context NUMBER := 0;
  conv_warning NUMBER := 0;
BEGIN
  file := bfilename('XMLDIR', 'tdadxdb-03-02.txt');
  DBMS_LOB.createTemporary(contents, true, DBMS_LOB.SESSION);
  DBMS_LOB.fileopen(file, DBMS_LOB.file_readonly);
  DBMS_LOB.loadClobfromFile(contents,
                            file,
                            DBMS_LOB.getLength(file),
                            dest_offset,
                            src_offset,
                            nls_charset_id('AL32UTF8'),
                            lang_context,
                            conv_warning);
  DBMS_LOB.fileclose(file);
  UPDATE RESOURCE_VIEW
    SET res = updateXML(res,
                        '/Resource/Contents/text/text()',
                        contents,
                        'xmlns="http://xmlns.oracle.com/xdb/XDBResource.xsd"')
      WHERE equals_path(res, '/home/QUINE/NurseryRhyme.txt') = 1;
  DBMS_LOB.freeTemporary(contents);
END;
/

関連するリソースの更新によって文書のコンテンツを更新する方法のメリットは、Oracle XML DBリポジトリに格納されたあらゆる種類の文書を更新できることです。

例3-58では、リソース・ドキュメントで更新処理を実行することによって、XML文書のノードを更新する方法を示します。ここでは、SQL関数updateXMLによって、User要素に関連付けられたテキスト・ノードの値を変更します。

例3-58 UPDATEとUPDATEXMLを使用したノードの更新

UPDATE RESOURCE_VIEW
  SET res = updateXML(res,
                      '/r:Resource/r:Contents/PurchaseOrder/User/text()',
                      'SKING',
                      'xmlns:r="http://xmlns.oracle.com/xdb/XDBResource.xsd"')
  WHERE equals_path(
          res,
          '/home/QUINE/PurchaseOrders/2002/Mar/SBELL-2002100912333601PDT.xml')
        = 1;
 
1 row updated.

SELECT XMLCast(XMLQuery(
                 'declare namespace ns="http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :)
                  $r/ns:Resource/ns:Contents/PurchaseOrder/User/text()'
                 PASSING RES AS "r" RETURNING CONTENT)
               AS VARCHAR2(32))
  FROM RESOURCE_VIEW
  WHERE equals_path(RES,
                    '/home/QUINE/PurchaseOrders/2002/Mar/SBELL-2002100912333601PDT.xml')
        = 1;
 
XMLCAST(XMLQUERY('DECLARENAMESPA
--------------------------------
SKING

1 row selected.

リポジトリ内のXML Schemaに基づく文書の更新

文書のコンテンツを管理するために使用するデフォルト表に対して更新操作を直接実行することによって、XML Schemaに基づくXML文書を更新できます。メタデータに基づくパスまたは条件が含まれたWHERE句を使用して文書を配置する必要がある場合、UPDATE文では、リソースとデフォルト表間の結合を使用する必要があります。

一般に、XML Schemaに基づくXML文書のコンテンツを更新する場合は、RESOURCE_VIEWまたはPATH_VIEWを単独で使用するよりも、RESOURCE_VIEWまたはPATH_VIEWをデフォルト表と結合して使用するほうが効率的です。リソース・ドキュメントとデフォルト表を明示的に結合することによって、Oracle XML DBは、SQL文が1種類のXML文書に対してのみ機能することを認識します。これによって、デフォルト表およびリソースで部分更新を使用できます。

例3-59では、SQL関数updateXMLは、パスによって識別されるターゲットの行を使用してデフォルト表を操作します。更新される行は、REFによって識別されます。REFは、SQL関数equals_pathを使用して、リポジトリ・パスによって識別されます。これにより、更新対象は、指定されたパスで識別されるリソースに対応する行のみに制限されます。

例3-59 リポジトリ内のXML Schemaに基づく文書の更新

UPDATE purchaseorder p
  SET p.OBJECT_VALUE = updateXML(p.OBJECT_VALUE, '/PurchaseOrder/User/text()', 'SBELL')
    WHERE ref(p) =
      (SELECT XMLCast(XMLQuery('declare default element namespace
                                "http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :)
                                fn:data(/Resource/XMLRef)' PASSING rv.RES RETURNING CONTENT)
                      AS REF XMLType)
         FROM RESOURCE_VIEW rv
         WHERE equals_path(rv.RES,
                           '/home/QUINE/PurchaseOrders/2002/Mar/SBELL-2002100912333601PDT.xml')
               = 1);

SELECT XMLCast(XMLQuery('$p/PurchaseOrder/User/text()'
                        PASSING p.OBJECT_VALUE AS "p" RETURNING CONTENT)
               AS VARCHAR2(32))
  FROM purchaseorder p, RESOURCE_VIEW rv
  WHERE ref(p) = XMLCast(XMLQuery('declare default element namespace
                                "http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :)
                                fn:data(/Resource/XMLRef)' PASSING rv.RES RETURNING CONTENT)
                      AS REF XMLType)
    AND equals_path(rv.RES, '/home/QUINE/PurchaseOrders/2002/Mar/SBELL-2002100912333601PDT.xml')
        = 1;

XMLCAST(XMLQUERY('$P/PURCHASEO
------------------------------
SBELL

リポジトリ・データへのアクセスの制御

アクセス制御リスト(ACL)を使用すると、Oracle XML DBリポジトリ内のリソースへのアクセスを制御できます。ACLはアクセス制御エントリ(ACE)のリストで、各エントリは、特定のプリンシパルへの一連の権限を付与または拒否します。プリンシパルとは、データベース・ユーザー、データベース・ロール、LDAPユーザー、LDAPグループ、またはリソースの所有者である特別なプリンシパルDAV::ownerです。リポジトリ内の各リソースは、ACLによって保護されます。ACLによって、ユーザーがリソースに対して持つ権限(read-propertiesupdateなど)が決まります。各リポジトリ操作には、現行ユーザーがその操作の実行を許可されているかどうかを判断するために、ACLの確認が含まれています。デフォルトでは、新規のリソースはその親フォルダのACLを継承します。ただし、PL/SQLプロシージャDBMS_XDB.setACLを使用してリソースのACLを設定することもできます。Oracle XML DBのリソースのセキュリティの詳細は、第27章「リポジトリのアクセス制御」を参照してください。

次の例で、現行ユーザーはQUINEです。問合せでは、フォルダ/publicのリソースの数が戻されます。このフォルダには、f1f2の2つのリソースのみが存在すると想定します。また、f1のACLではread-properties権限がQUINEに付与されますが、f2のACLではQUINEに付与される権限はないと想定します。ユーザーがリソースを参照するには、そのリソースに対するread-properties権限が必要です。QUINEf1のみ参照できるため、問合せの結果は1です。

SELECT count(*) FROM RESOURCE_VIEW r WHERE under_path(r.res, '/public') = 1;
 
COUNT(*)
--------
       1

Oracle XML DBのトランザクション・セマンティクス

SQLを使用して作業をしている場合は、通常のトランザクション動作が適用されます。1つの論理作業単位内では、updateXMLなどのSQL関数のコールを複数回使用できます。updateXMLなどの関数を使用して実行された変更は、トランザクションがコミットされるまで他のデータベース・ユーザーから参照されません。任意の時点でROLLBACKを使用して、前回のコミット以降に行われた一連の変更をバック・アウトできます。

メタデータとフォルダ階層の問合せ

Oracle XML DBには、各リソースのシステム定義のメタデータがXML文書として保持されています。これらのリソース・ドキュメントの構造は、XML Schema XDBResource.xsdによって定義されます。このスキーマは、グローバルXML SchemaとしてURL http://xmlns.oracle.com/xdb/XDBResource.xsdに登録されています。

Oracle XML DBを使用すると、2つのパブリック・ビュー(RESOURCE_VIEWおよびPATH_VIEW)を使用して、メタデータおよびフォルダ階層に関する情報にアクセスできます。

RESOURCE_VIEWおよびPATH_VIEW

RESOURCE_VIEWには、Oracle XML DBリポジトリに格納されたファイルまたはフォルダごとに1つのエントリが含まれています。RESOURCE_VIEWの列RESにはリソース(リソースのコンテンツに関連付けられたメタデータ・プロパティを管理するXML文書)が含まれます。列ANY_PATHには、リソースのコンテンツにアクセスするために現行ユーザーがXDBURITypeに渡すことができる有効なURLが含まれます。このコンテンツがバイナリ・データでない場合、リソースそのものにもコンテンツが含まれます。

Oracle XML DBは、リンクの概念をサポートしています。リンクによって、指定した文書への複数のパスを定義できます。リンク・プロパティ文書と呼ばれる各XML文書では、(リソース固有ではなく)パス固有のメタデータ・プロパティが保持されます。リソースが作成されるたびに、最初のリンクも作成されます。

PATH_VIEWは、リンク・プロパティ文書を公開します。PATH_VIEWには、文書に対してアクセス可能なパスごとに1つのエントリがあります。PATH_VIEWの列RESには、このリンクの参照先のリソース・ドキュメントが含まれます。列PATHには、リンクがリソースへのアクセスに使用できるパスが含まれます。列LINKには、このPATHのリンク・プロパティ文書(メタデータ)が含まれます。

例3-60では、パブリック・ビューRESOURCE_VIEWおよびPATH_VIEWの内容を示します。

例3-60 RESOURCE_VIEWおよびPATH_VIEWの構造の表示

DESCRIBE RESOURCE_VIEW

Name      Null?    Type
-------------------------------------------------------------
RES                SYS.XMLTYPE(XMLSchema 
                               "http://xmlns.oracle.com/xdb/XDBResource.xsd" 
                               Element 
                               "Resource")
ANY_PATH           VARCHAR2(4000)
RESID              RAW(16)


DESCRIBE PATH_VIEW

Name      Null?    Type
-------------------------------------------------------------
PATH               VARCHAR2(1024)
RES                SYS.XMLTYPE(XMLSchema
                               "http://xmlns.oracle.com/xdb/XDBResource.xsd" 
                               Element 
                               "Resource")
LINK               SYS.XMLTYPE
RESID              RAW(16)

関連項目:


RESOURCE_VIEWおよびPATH_VIEW内のリソースの問合せ

Oracle XML DBには、フォルダ限定の問合せを実行するために使用するSQL関数として、equals_pathおよびunder_pathの2つが用意されています。このような問合せは、RESOURCE_VIEWまたはPATH_VIEWを操作するSQL文を、Oracle XML DBのフォルダ階層内の特定の場所にある文書に制限します。関数equals_pathは、SQL文を、指定したパスで識別される単一の文書に制限します。関数under_pathは、SQL文を、階層内の特定の場所より下位に存在する文書に制限します。

次の各例に、RESOURCE_VIEWおよびPATH_VIEWに格納されたリソース・ドキュメントに対する簡単なフォルダ限定の問合せを示します。

例3-61の問合せは、SQL関数equals_pathおよびRESOURCE_VIEWを使用して、例3-60で作成したリソースにアクセスします。

例3-61 EQUALS_PATHおよびRESOURCE_VIEWを使用したリソースへのアクセス

SELECT XMLSerialize(DOCUMENT r.res AS CLOB)
  FROM RESOURCE_VIEW r
  WHERE equals_path(res, '/home/QUINE/NurseryRhyme.txt') = 1;
 
XMLSERIALIZE(DOCUMENTR.RESASCLOB)
--------------------------------------------------------------------------------
<Resource xmlns="http://xmlns.oracle.com/xdb/XDBResource.xsd" 
          Hidden="false" 
          Invalid="false" 
          Container="false" 
          CustomRslv="false" 
          VersionHistory="false" 
          StickyRef="true">
  <CreationDate>2005-06-13T13:19:20.566623</CreationDate>
  <ModificationDate>2005-06-13T13:19:22.997831</ModificationDate>
  <DisplayName>NurseryRhyme.txt</DisplayName>
  <Language>en-US</Language>
  <CharacterSet>UTF-8</CharacterSet>
  <ContentType>text/plain</ContentType>
  <RefCount>1</RefCount>
  <ACL>
    <acl description=
         "Private:All privileges to OWNER only and not accessible to others"
         xmlns="http://xmlns.oracle.com/xdb/acl.xsd" xmlns:dav="DAV:"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://xmlns.oracle.com/xdb/acl.xsd
         http://xmlns.oracle.com/xdb/acl.xsd"
         shared="true">
      <ace>
        <grant>true</grant>
        <principal>dav:owner</principal>
        <privilege>
          <all/>
        </privilege>
      </ace>
    </acl>
  </ACL>
  <Owner>QUINE</Owner>
  <Creator>QUINE</Creator>
  <LastModifier>QUINE</LastModifier>
  <SchemaElement>http://xmlns.oracle.com/xdb/XDBSchema.xsd#text</SchemaElement>
  <Contents>
    <text>Hickory Dickory Dock
The Mouse ran up the clock
The clock struck one
The Mouse ran down
Hickory Dickory Dock
    </text>
  </Contents>
</Resource>
 
1 row selected.

例3-61に示すように、リソース・ドキュメントは、DAV標準で定義された一連のメタデータを取得するXML文書です。メタデータには、CreationDateCreatorOwnerModificationDateDisplayNameなどの情報が含まれています。リソース・ドキュメントのコンテンツは、SQL/XMLアクセスおよび問合せ関数を使用して、他のXML文書と同様の方法で問合せおよび更新ができます。

例3-62の問合せにより、Oracle XML DBリポジトリに格納された各XSLスタイルシートへのパスを検索します。これは.xslで終わるDisplayNameの検索を実行します。

例3-62 リポジトリに格納されたXSLスタイルシートへのパスの判別

SELECT ANY_PATH FROM RESOURCE_VIEW
  WHERE XMLCast(XMLQuery(
                  'declare namespace ns="http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :)
                   $r/ns:Resource/ns:DisplayName'
                  PASSING RES AS "r" RETURNING CONTENT)
                AS VARCHAR2(100))
        LIKE '%.xsl';
 
ANY_PATH
-------------------------------------------
/source/schemas/poSource/xsl/empdept.xsl
/source/schemas/poSource/xsl/purchaseOrder.xsl
 
2 rows selected.

例3-63の問合せでは、パス/home/QUINE/PurchaseOrdersの下に存在するリソース(ファイルおよびフォルダ)の数をカウントします。PATH_VIEWではなくRESOURCE_VIEWを使用すると、複数リンクのターゲットであるリソースは1回のみカウントされます。SQL関数under_pathを使用すると、結果セットは、/home/QUINE/PurchaseOrdersで始まるパスを使用してアクセス可能な文書に制限されます。

例3-63 パスの下に存在するリソースのカウント

SELECT count(*)
   FROM RESOURCE_VIEW
   WHERE under_path(RES, '/home/QUINE/PurchaseOrders') = 1;
 
  COUNT(*)
----------
       145

1 row selected.

例3-64の問合せは、パス/home/QUINE/PurchaseOrders/2002/Aprで識別されるフォルダのコンテンツをリストします。この問合せによって、フォルダ内のディレクトリのリストを効率的に作成できます。

例3-64 パス内のフォルダのコンテンツのリスト

SELECT PATH
  FROM PATH_VIEW
  WHERE under_path(RES, '/home/QUINE/PurchaseOrders/2002/Apr') = 1;
 
PATH
----------------------------------------------------------------------
/home/QUINE/PurchaseOrders/2002/Apr/AMCEWEN-20021009123336171PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/AMCEWEN-20021009123336271PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/EABEL-20021009123336251PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/PTUCKER-20021009123336191PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/PTUCKER-20021009123336291PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/SBELL-20021009123336231PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/SBELL-20021009123336331PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/SKING-20021009123336321PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/SMCCAIN-20021009123336151PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/SMCCAIN-20021009123336341PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/VJONES-20021009123336301PDT.xml
 
11 rows selected.

例3-65の問合せは、パス/home/QUINE/PurchaseOrders/2002/Aprで識別されるフォルダに含まれる、関連するリソースのDisplayName要素がSで始まる一連のリンクをリストします。

例3-65 フォルダに含まれているリンクのリスト

SELECT PATH
  FROM PATH_VIEW
  WHERE XMLCast(XMLQuery(
                  'declare namespace ns="http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :)
                   $r/ns:Resource/ns:DisplayName'
                  PASSING RES AS "r" RETURNING CONTENT)
                AS VARCHAR2(100))
        LIKE 'S%'
    AND under_path(RES, '/home/QUINE/PurchaseOrders/2002/Apr') = 1;
 
PATH
----------------------------------------------------------------------
/home/QUINE/PurchaseOrders/2002/Apr/SBELL-20021009123336231PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/SBELL-20021009123336331PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/SKING-20021009123336321PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/SMCCAIN-20021009123336151PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/SMCCAIN-20021009123336341PDT.xml
 
5 rows selected.

例3-66の問合せにより、PurchaseOrder文書を含む、Oracle XML DBリポジトリの各リソースへのパスを検索します。文書はXML Schema URLおよびリポジトリに格納されたスキーマに基づくXMLデータのグローバル要素を識別する、メタデータ・プロパティSchemaElementに基づき識別されます。

例3-66 発注書のXML文書が含まれたリソースへのパスの検索

SELECT ANY_PATH
  FROM RESOURCE_VIEW
 WHERE XMLExists(
         'declare namespace ns="http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :)
          $r/ns:Resource[ns:SchemaElement=
          "http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd#PurchaseOrder"]'
         PASSING RES AS "r");

この問合せは次のパスを戻します。それぞれのパスにPurchaseOrder文書が含まれています。

ANY_PATH
-----------------------------------------------------------------------
/home/QUINE/PurchaseOrders/2002/Apr/AMCEWEN-20021009123336171PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/AMCEWEN-20021009123336271PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/EABEL-20021009123336251PDT.xml
/home/QUINE/PurchaseOrders/2002/Apr/PTUCKER-20021009123336191PDT.xml

...

132 rows selected.

Oracle XML DBの階層リポジトリ索引

従来のリレーショナル・データベースでは、パスベースのアクセスおよびフォルダ限定の問合せはCONNECT BY操作を使用して実装します。このような問合せはコストがかかるため、パスベースのアクセスおよびフォルダ限定の問合せは、文書の数やフォルダ階層の深さが増すにつれて効率が下がります。

この問題に対処するために、Oracle XML DBでは階層リポジトリ索引という新しい索引タイプが導入されました。これを使用すると、CONNECT BY操作を使用しなくても、データベースでフォルダ限定の問合せを解決できます。したがって、Oracle XML DBでは、パスベースおよびフォルダ限定の問合せを効率的に実行できます。階層リポジトリ索引は、Oracleのドメイン索引として実装されます。これは、Oracle Text索引のサポートおよび他の多数の高度な索引タイプをデータベースに追加する場合の方法と同じです。

例3-67では、フォルダ限定の問合せで生成された実行計画の出力を示します。次に示すように、階層リポジトリ索引(XDBHI_IDX)を使用して問合せを解決します。

例3-67 フォルダ限定の問合せの実行計画の出力

SELECT PATH
  FROM PATH_VIEW
  WHERE XMLCast(
          XMLQuery(
            'declare namespace ns="http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :)
             $r/ns:Resource/ns:DisplayName'
            PASSING RES AS "r" RETURNING CONTENT)
          AS VARCHAR2(100))
        LIKE 'S%'
    AND under_path(RES, '/home/QUINE/PurchaseOrders/2002/Apr') = 1;
 
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------
Plan hash value: 2568289845
 
------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |               |    17 |  3111 |    34   (6)| 00:00:01 |
|   1 |  NESTED LOOPS                        |               |    17 |  3111 |    34   (6)| 00:00:01 |
|   2 |   NESTED LOOPS                       |               |    17 |  2822 |    34   (6)| 00:00:01 |
|   3 |    NESTED LOOPS                      |               |   466 | 63842 |    34   (6)| 00:00:01 |
|*  4 |     TABLE ACCESS BY INDEX ROWID      | XDB$RESOURCE  |     1 |   135 |     3   (0)| 00:00:01 |
|*  5 |      DOMAIN INDEX                    | XDBHI_IDX     |       |       |            |          |
|   6 |     COLLECTION ITERATOR PICKLER FETCH|               |       |       |            |          |
|*  7 |    INDEX UNIQUE SCAN                 | XDB_PK_H_LINK |     1 |    28 |     0   (0)| 00:00:01 |
|*  8 |   INDEX UNIQUE SCAN                  | SYS_C003900   |     1 |    17 |     0   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   4 - filter(CAST("P"."SYS_NC00011$" AS VARCHAR2(100)) LIKE 'S%')
   5 - access("XDB"."UNDER_PATH"(SYS_MAKEXML('8758D485E6004793E034080020B242C6',734,"XMLEXTRA"
              ,"XMLDATA"),'/home/QUINE/PurchaseOrders/2002/Apr',9999)=1)
   7 - access("H"."PARENT_OID"=SYS_OP_ATG(VALUE(KOKBF$),3,4,2) AND
              "H"."NAME"=SYS_OP_ATG(VALUE(KOKBF$),2,3,2))
   8 - access("R2"."SYS_NC_OID$"=SYS_OP_ATG(VALUE(KOKBF$),3,4,2))
 
25 rows selected.

文書をリポジトリに格納する方法

Oracle XML DBでは、XML文書を特別な方法で処理します。XML Schemaに基づくXML文書のコンテンツを格納するルールは、XML Schemaで定義されます。文書のコンテンツは、グローバル要素定義に関連付けられたデフォルト表に格納されます。

Oracle XML DBリポジトリには、JPEGイメージやWord文書など、XMLデータを含まないファイルも格納されます。各リソースのXML Schemaでは、使用可能な要素を定義し、ファイルのコンテンツをBLOBインスタンスとして格納するか、またはCLOBインスタンスとして格納するかを指定します。XML Schemaに基づかないXML文書のコンテンツは、CLOBインスタンスとしてリポジトリに格納されます。

リポジトリ内のファイルまたはフォルダごとに、1つのリソースおよび1つのリンク・プロパティ文書が存在します。指定した文書へのアクセス・パスが複数存在する場合は、リンクごとにリンク・プロパティ文書が存在します。リソース・ドキュメントおよびリンク・プロパティ文書は、両方ともXML文書として格納されます。これらの文書はすべてリポジトリ内の表に格納されます。

XMLファイルをリポジトリにロードすると、次の順序でイベントが発生します。

  1. Oracle XML DBは、XML文書のルート要素を調べ、既知(登録済)のXML Schemaに関連付けられているかどうかを確認します。このとき、文書にXMLSchema-instance名前空間の名前空間宣言が含まれているかどうかが確認され、文書に関連付けられたXML Schemaを識別するschemaLocation属性またはnoNamespaceSchemaLocation属性が検索されます。

  2. 文書が既知のXML Schemaに基づいている場合は、XML SchemaのメタデータがXML Schemaのキャッシュからロードされます。

  3. XML文書は解析され、XML Schemaから導出された一連のSQLオブジェクトに分解されます。

  4. XMLファイルから作成されたSQLオブジェクトは、XML Schemaがデータベースに登録されたときに定義されたデフォルト表に格納されます。

  5. リソース・ドキュメントは、処理された文書ごとに作成されます。これによって、リポジトリを使用して、文書のコンテンツにアクセスできます。XML Schemaに基づくXMLTypeインスタンスのリソース・ドキュメントには、XMLRef要素が含まれています。この要素には、リソースに関連付けられたコンテンツが含まれるデフォルト表内の行を検索するときに使用できるXMLTypeREFが含まれます。

ブラウザを使用した、リレーショナル・データのXMLとしての表示

Oracle XML DBに組み込まれたHTTPサーバーでは、ブラウザを使用して、Oracle XML DBリポジトリに格納された文書にアクセスできます。リソースにはXMLType表またはビューの行に対するREFを含めることができるため、パスを使用してこのようなコンテンツにアクセスできます。

DBUri SERVLETを使用した、ブラウザからの表またはビューへのアクセス

Oracle XML DBに含まれているDBUriサーブレットを使用すると、ブラウザからすべての表またはビューのコンテンツに直接アクセスできます。DBUriサーブレットは、DBURITypeの機能を使用し、表のコンテンツから簡単なXML文書を生成します。サーブレットはC言語ベースで、Oracle XML DB HTTPサーバーにインストールされます。デフォルトでは、サーブレットは仮想ディレクトリ/oradbにインストールされます。

DBUriサーブレットに渡されるURLは、DBURITypeに渡されるURLの拡張です。このURLは、Oracle XML DB HTTPサーバーのアドレスとポート番号、およびHTTP(S)リクエストをDBUriサーブレットに転送する仮想ルートを使用して拡張されています。このURLのデフォルト構成は/oradbです。

したがって、URL http://localhost:8080/oradb/HR/DEPARTMENTSは、HRデータベース・スキーマにあるDEPARTMENTS表のコンテンツが含まれるXML文書を戻します。この場合、Oracle XML DB HTTPサーバーはポート8080で実行され、DBUri servletの仮想ルートは/oradbで、リクエストを発行したユーザーにはHRデータベース・スキーマに対するアクセス権限があると想定されます。

DBUriサーブレットは、ROWタグの名前、およびクライアントに戻される文書のMIMEタイプを指定できるパラメータを受け取ります。

XMLType表またはビューのコンテンツにも、DBUri servletを介してアクセスできます。DBUri servletに渡されるURLでXMLType表またはXMLTypeビューを参照する場合は、表または行内のどの文書が戻されるかを判別できるXPath式を使用してURLを拡張できます。URLに追加するXPath式は、文書内のすべてのノードを参照できます。

DBUriサーブレットで生成されたXMLは、Oracle XML DBに組み込まれているXSLTプロセッサを使用して変換できます。これによって、DBUri servletで生成されたXMLを、HTMLなど読みやすい形式で表示できます。


関連項目:

「DBUriServlet」

スタイルシート処理を開始するには、DBUriサーブレットに渡されるURLの一部としてtransformパラメータを指定します。スタイルシートは、そのスタイルシートのデータベース内での場所を参照するURIを使用して指定します。URIは、表またはビュー内のXMLType列を識別するDBURIType値、またはOracle XML DBリポジトリに格納された文書へのパスのいずれかになります。スタイルシートは、生成されたXMLがクライアントに戻される前に、XMLに直接適用されます。DBUriサーブレットを使用してXSLT処理を実行するときは、contenttypeパラメータを使用して、生成された出力のMIMEタイプを明示的に指定することをお薦めします。

変換されるXML文書がXML Schemaに基づくXMLTypeインスタンスとして格納されると、Oracle XML DBは、遅延ロードされた仮想DOMの機能を使用できるため、XSL変換に関連するオーバーヘッドを削減できます。

URLのルートは/oradbであるため、このURLは、Oracle XML DBリポジトリのリソースとしてではなく、SCOTTデータベース・スキーマのpurchaseorder表にアクセスするDBUriサーブレットに渡されます。このURLには、結果セットを、述語で指定した値がノード/PurchaseOrder/Reference/text()に含まれる文書に制限するXPath式が含まれます。contenttypeパラメータは、生成される文書のMIMEタイプをtext/xmlに設定します。

DBUriサーブレットを使用したXSL変換

図3-7に、DBUriサーブレットで生成されたXMLコンテンツにXSL変換を適用する方法を示します。この例では、DBUriに渡すURLにtransformパラメータが含まれています。これによって、DBUriサーブレットは、メインのURLで識別されるPurchaseOrder文書がブラウザに戻される前に、Oracle SQL関数XMLTransformを使用して、スタイルシート/home/SCOTT/xsl/purchaseOrder.xslを文書に適用します。このスタイルシートによって、XML文書がわかりやすいHTMLページに変換されます。また、URLでは、contentTypeパラメータを使用して、最後の文書のMIMEタイプがtext/htmlになることを指定します。

図3-7 DBUriサーブレットを使用したPurchaseOrderのデータベースXSL変換

図3-7の説明が続きます
「図3-7 DBUriサーブレットを使用したPurchaseOrderのデータベースXSL変換」の説明

図3-8に、HTML文書として表示されたdepartments表を示します。コーディングは不要で、これを表示するためには、SQL/XML関数に基づくXMLTypeビュー、業界標準のXSLスタイルシートおよびDBUriサーブレットのみが必要です。

図3-8 DBUriサーブレットを使用したDepartments表のデータベースXSL変換

図3-8の説明が続きます
「図3-8 DBUriサーブレットを使用したDepartments表のデータベースXSL変換」の説明



脚注の凡例

脚注1: XML Schemaに基づくデータのXMLType記憶域モデルは、参照するXML Schemaの登録時に指定したものです。登録時に記憶域モデルを指定しなかった場合は、バイナリXML記憶域が使用されます。
脚注2: XML Schema注釈maintainOrder = "false"を使用すると、Ordered Collectionでなく、Unordered Collectionが使用されます。XMLデータの場合、ドキュメント内の順序を保持するために、Ordered Collection(maintainOrder = "true")を使用することをお薦めします。デフォルトでは、属性maintainOrdertrueです。