この章では、Oracle XML DBの使用方法について概説します。この章の例では、発注書のXMLコンテンツへのアクセスおよび管理の方法を示します。発注書は高度に構造化された文書ですが、ほとんど構造化されていないXML文書に対しても、ここに示す方法を使用することができます。
この章の内容は次のとおりです。
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
は、データベースの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
データ型および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
表または列を容易に作成することができます。記憶域オプションと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);
注意: 各自のデータベース・スキーマと異なるデータベース・スキーマにXMLType 表を作成するには、権限CREATE ANY TABLE だけでなく、権限CREATE ANY INDEX も必要です。これは、表の作成時に列OBJECT_ID に一意索引が作成されるためです。列OBJECT_ID には、システム生成のオブジェクト識別子が格納されます。 |
XMLデータには独自の構造がありますが、XMLType
のオブジェクト・リレーショナル記憶域を除き、データベースのデータ構造には直接反映されません。つまり、個別のXML要素および属性がデータベースの個別の列や表にマップされることはありません。
したがって、個別の要素や属性の値に応じてXMLデータを制約またはパーティション化する場合、リレーショナル・データの標準的な手法は適用できません。このため、対象のXMLデータを表す仮想列を作成してから、その仮想列を使用して必要な制約またはパーティションを定義する必要があります。
この方法は、バイナリXMLとして格納されているXMLデータにのみ適用されます。非構造化記憶域を使用するXMLデータの場合、データベースはXML構造を認識せず、データはフラット・テキストとして扱われますが、バイナリXML記憶域の場合、構造が認識されます。この構造についての情報を使用して仮想列を作成すると、データベースではそれを制約またはパーティションに使用できます。
手順は次のとおりです。
対象のXMLデータに対応する仮想列を定義します。
その列を使用して、XMLType
データを一括してパーティション化または制約します。
XMLType
データに対する仮想列の作成は、他の型のデータを使用した仮想列の作成と同様ですが、構文が多少異なります。特に、列定義に関連付けて制約を指定することができません。
XMLType
は抽象データ型なので、仮想列をXMLType
表に作成する場合、それらの列は非表示になります。これらはDESCRIBE
文などに表示されません。表示されないことで、DESCRIBE
などの操作を使用するツールが、仮想列に惑わされずに正常に機能することができます。
注意:
|
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を参照してください。
関連項目:
|
XMLコンテンツは、次の方法を使用してOracle XML DBにロードできます。
表ベースのロード:
パスベースのリポジトリのロード方法:
SQLまたはPL/SQLの簡単なINSERT
操作を使用して、XML文書をデータベースにロードできます。文書は、XMLType
列または表として格納する前に、XMLType
コンストラクタの1つを使用してXMLType
インスタンスに変換する必要があります。
関連項目:
|
XMLType
コンストラクタを使用すると、VARCHAR
、CLOB
およびBFILE
値を含む様々なソースからXMLType
インスタンスを作成できます。このコンストラクタは、XMLType
の作成に関連する処理量を減らす追加の引数を受け入れます。たとえば、ソースのXML文書が有効だとわかっている場合には、有効かどうかわからない場合に実行される型チェックを無効にする引数をコンストラクタに指定できます。
さらに、ソース・データがデータベース・キャラクタ・セットでエンコードされていない場合、XMLType
インスタンスはBFILE
値またはBLOB
値を使用して構成できます。ソース・データのエンコーディングは、コンストラクタのキャラクタ・セットID(csid
)引数で指定されます。
例3-5に、XMLコンテンツをXMLType
表に挿入する方法を示します。この挿入を行う前に、処理するファイルが含まれたディレクトリを指すデータベース・ディレクトリ・オブジェクトを作成する必要があります。作成するためには、CREATE ANY DIRECTORY
権限が必要です。
関連項目: 『Oracle Database SQL言語リファレンス』の第18章のGRANT に関する項 |
例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によってロード時間とメモリー使用量が最適化されます。
例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インタフェースです。
例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セキュリティ・ガイド』を参照してください。 |
小規模なXML文書のコレクションで構成された大規模なXMLファイルをロードするときは、Simple API for XML(SAX)の解析機能を使用してファイルを一連の小規模な文書に分割してから文書を挿入すると、効率的にロードできます。SAXは、XML Parserがイベント・ベース・アプリケーション用に提供するXML標準インタフェースです。
SAXを使用して、ノードのコレクションから各文書を作成することによって、30MB以上の大規模なXMLファイルからデータベース表をロードできます。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
オプションを使用して、各データ保存で読み取られる行数を少なくします。
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
にコピーする簡単なドラッグ・アンド・ドロップ操作を示します。
コピーされたフォルダには、XML Schema文書、HTMLページおよびいくつかのXSLTスタイルシートが含まれていることがあります。
この項では、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文書内の各エンティティでは、異なるエンコーディングの文字が使用される場合があります。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
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
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データをVARCHAR
、CLOB
または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
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勧告では、一連のXML文書の構造、コンテンツおよび特定のセマンティクスを指定するための標準化された言語が定義されています。XML Schemaは、XML文書のクラスを示すメタデータとみなすことができます。XML Schemaの勧告については、http://www.w3.org/TR/xmlschema-0/
を参照してください。
指定のXML Schemaに準拠する文書は、そのXML Schemaで定義されたクラスのメンバーまたはインスタンスとみなすことができます。したがって、インスタンス・ドキュメントという用語は、多くの場合、指定したXML Schemaに準拠するXML文書を示すために使用しています。XML Schemaの最も一般的な用途は、指定されたインスタンス・ドキュメントがXML Schemaで定義されたルールに準拠していることを確認することです。
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は、次のいずれかを使用して作成および編集できます。
emacsやviなどの簡単なテキスト・エディタ
Oracle JDeveloperに付属のXMLエディタなど、XML Schemaを認識するエディタ
Altova社のXMLSpyなどの明示的なXML Schema作成ツール
XML Schema言語は、47のスカラー・データ型を定義します。これによって、要素と属性の厳密な型指定が可能になります。W3CのXML Schema勧告では、継承や拡張などのオブジェクト指向の技法もサポートしているため、XML Schema言語で定義された基本データ型から複合的なオブジェクトを持つXML Schemaを設計できます。ボキャブラリには、定義および順序付けの構造体、デフォルト値、必須コンテンツ、ネスト、セットの繰返しおよび再定義が含まれます。Oracle XML DBは、再定義を除くすべての構造体をサポートします。
例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>
図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によるグラフィカル表現
この発注書XML Schemaは、次のような一般的なXML文書の主要な機能を示しています。
グローバル要素PurchaseOrder
は、complexType
PurchaseOrderType
のインスタンスです。
PurchaseOrderType
では、PurchaseOrder
要素を構成する一連のノードが定義されます。
LineItem
要素は、LineItems
要素のコレクションで構成されます。
各LineItem
要素は、2つの要素(Description
およびPart
)で構成されます。
Part
要素には、属性Id
、Quantity
およびUnitPrice
があります。
この項では、Oracle XML DBでのXML Schemaの使用について説明します。
次に、XML SchemaをOracle XML DBとともに使用する主な理由を説明します。
XML Schemaの最も一般的な用途は、インスタンス・ドキュメントが指定のXML Schemaに準拠していることを確認するメカニズムとして使用することです。XMLType
メソッドisSchemaValid()
およびschemaValidate()
によって、XMLType
として格納されたインスタンス・ドキュメントのコンテンツを検証します。
XML Schemaは、XMLType
の表または列の作成時に制約としても使用できます。たとえば、XMLType
は、XML Schemaで定義されたいずれかのグローバル要素に準拠するXML文書の格納用に制限されます。
Oracle XML DBでは、XML Schemaを、XMLType
インスタンスのコンテンツをデータベース内に格納する方法を定義するメカニズムとしても使用します。バイナリXML、構造化、非構造化およびハイブリッド(構造化と非構造化の組合せ)のすべての記憶域モデルで、XML Schemaの使用をサポートしています。XMLType
に使用可能な記憶域モデルの詳細は、「XMLType記憶域モデル」を参照してください。
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コンテンツの問合せおよび更新に必要なメモリーの量も削減できます。
W3CのXML Schema勧告では、ベンダー固有の情報をXML Schemaに追加できる注釈メカニズムが定義されています。Oracle XML DBでは、このメカニズムを使用して、XML Schemaとデータベース・オプションの間のマッピングを制御します。
XML Schema注釈を使用すると、次の操作を実行できます。
XMLデータを格納するデータベース表の指定
XML Schemaデータ型とSQLデータ型(構造化記憶域の場合)の間のデフォルト・マッピングの上書き
XMLデータを格納するために作成されるデータベース・オブジェクトおよび属性の命名(構造化記憶域の場合)
オブジェクト・リレーショナルに格納されるデータのXML Schemaを登録し、登録パラメータGENTABLES
をTRUE
に設定する場合、関連付けられた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.registerSchema
のOPTIONS
パラメータでREGISTER_NT_AS_IOT
を渡します。
注意: OracleからIOTの使用を明示的に指示された場合を除き、IOTでなく、ヒープに基づくOCTを使用してください。IOTの記憶域には、次のような大きな制限があります。
XMLデータでのOracle Textの使用方法の詳細は、第12章「XMLデータの全文検索」を参照してください。 |
注意: Oracle Database 11gリリース1より前のリリースの場合:
|
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に容易に追加できます。
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
表の作成
例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_t
、lineitem_v
およびlineitem_t
。これらの型はPurchaseOrder
文書に存在する可能性のあるLineItem
要素のコレクションを管理します。型lineitems_t
は、型lineitem_v
のインスタンスとして定義された単一の属性lineitem
で構成されます。型lineitem_v
はlinteitem_t
オブジェクトのVARRAYとして定義されます。文書内の各LineItem
要素に対し、lineitem_t
オブジェクトのインスタンスが1つずつあります。
大規模で複雑な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>'
|
エラー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は、XMLType
のREF
を使用して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の登録時にパラメータGENTABLES
をFALSE
に設定し、インスタンス・ドキュメントのルート要素として正当に表示できる各グローバル要素に対してデフォルト表を手動で作成します。この方法を使用すると、デフォルト表の自動作成は行われません。必要な表のみを手動で作成します。
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登録の際、パラメータGENTABLES
をTRUE
に設定すると、Oracle XML DBにより自動生成されるCREATE TABLE
文と同等です。デフォルトでは、XML Schema注釈storeVarrayAsTable
の値はtrue
で、XML Schema登録時に、コレクションに対してOrdered Collection Tables(OCT)を自動生成します。このOCTにはシステムが生成した、覚えにくい名前が付けられます。SQL文RENAME TABLE
を使用して、わかりやすい名前を付けることができます。
例3-13のCREATE TABLE
文は、単一レベルのネストが行われている発注書に対応しています。LineItem
要素のコレクションを管理するVARRAYは、Ordered Collection Table、lineitem_table
です。
ここで、別のXML Schemaを想定し、Shipment
要素のコレクションがShipments
要素内にあり、この要素がLineItem
要素内にあるとします。この場合は、例3-14に示すように、表を手動で作成できます。
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-15のDESCRIBE
文の出力には、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文書をXML Schemaに基づくXMLType
表または列に挿入する前に、関連付けられているXML Schemaを識別する必要があります。識別するには、次の2つの方法があります。
XMLType
の作成時に明示的にXML Schemaを識別します。これを行うには、XML Schemaの名前をXMLType
コンストラクタに渡すか、またはXMLType
のcreateSchemaBasedXML()
メソッドを起動します。
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つまたは両方の属性が必要です。
ターゲットの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">
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
コンストラクタかXMLType
のcreateSchemaBasedXML()
メソッドを使用してXML文書がXML Schemaに明示的に関連付けられている必要があります。
制限されているXML SchemaでtargetNamespace
が宣言されている場合、インスタンス・ドキュメントには、XML Schemaで定義されたtargetNamespace
に文書のルート要素を配置するための適切な名前空間宣言が含まれている必要があります。
注意: XMLによる制限は、個々のXML文書内で適用されます。データベース(SQL)による制限は、一連のXML文書にわたって適用されます。 |
この項では、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
トリガーの場合は、必要なコーディングが表レベルの制約よりわずかに多くなります。このトリガーでは、XMLType
のschemaValidate()
メソッドを起動してXML文書を検証します。schemaValidate()
を使用するメリットは、例外が発生した場合にそのインスタンス・ドキュメントの問題点に関する追加情報が提供されることです。また、BEFORE INSERT
トリガーを使用すると、無効な文書が存在する場合に適切な処置を行うことができます。
バイナリ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'
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と同様の一意性制約を定義していますが、標準のデータベース・スキーマOE
のXMLType
表purchaseorder
における一意性制約も定義しています。さらに、各発注書の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.xml
のReference
要素に関連付けられたテキスト・ノードに、XML文書PurchaseOrder.xml
内の対応するノードと同じ値が含まれています。したがって、両方の文書をOracle XML DBに格納しようとすると、制約reference_is_unique
に違反します。
また、XML文書InvalidUser.xml
のUser
要素に関連付けられたテキスト・ノードには、値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コンテンツを管理するもう1つの主なメリットは、Oracle Databaseの機能を使用してXMLコンテンツの問合せと更新を行う強力で柔軟な機能が提供されることです。次の機能が含まれます。
XML文書内のノードとフラグメントの取出し
XML文書内のノードとフラグメントの更新
XML文書内の特定ノード上での索引の作成
XML文書のコンテンツ全体の索引付け
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関数または |
この項では、Oracle XML DBの問合せ方法およびXMLコンテンツの取出し方法について説明します。この項の内容は次のとおりです。
この項では、例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
は、オブジェクト表の値の別名として使用できます。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.
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.
テキスト・ノードおよび属性値には、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.
関連項目:
|
SQL/XML標準関数XMLExists
は、指定された文書にW3CのXPath式と一致するノードが含まれているかどうかを評価します。関数XMLExists
は、関数に指定されたXPath式によって指定されたノードが文書に含まれている場合はブール値のtrue
を、そうでない場合はfalse
の値を戻します。XPath式には述語を含めることができるため、XMLExists
は、指定されたノードが文書内に存在するかどうか、および指定された値を持つノードが文書内に存在するかどうかを判断できます。
同様に、SQL WHERE
句でSQL/XML関数XMLCast
およびXMLQuery
を使用すると、一部のプロパティを満たす文書のみを問合せの結果として戻すことができます。例3-27に、XMLExists
、XMLCast
および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
属性値が715515009058
のPart
要素が含まれている必要があります。
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
属性値が715515009058
のPart
要素が含まれます。
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
要素を検索します。関数XMLExists
をWHERE
句で使用して、選択する行を決定し、XMLQuery
をSELECT
リストで使用して、選択された文書のどの部分を結果に表示するかを制御します。
例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.
関連項目:
|
例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式を評価するためのコンテキストとしてXMLType
表purchaseorder
のコンテンツ(OBJECT_VALUE
)を使用することを指定しています。
したがって、XMLTable
式はpurchaseorder
表に依存します。これは左側結合です。この相関結合によって、アクセスされるpurchaseorder
行と、XMLTable
によってその行から生成される行は、1対多(1:N)の関係であることが保証されます。この相関結合により、purchaseorder
表は、FROM
リストのXMLTable
式よりも前に記述する必要があります。これは、PASSING
句が表の列を参照する場合に一般的な要件です。
仮想表のXMLType
インスタンスにはそれぞれ、Description
要素が1つずつ含まれます。XMLTable
のCOLUMNS
句を使用して、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 BY
やGROUP 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 BY
はLineItem
要素が属するPurchaseOrder
要素を正しく判別できます。
例3-31では、SQL/XML関数XMLTable
を使用して、指定された要素の子要素の数をカウントする方法を示します。XMLTable
に渡されるXPath式には、PurchaseOrder
要素の直接の子孫である全要素と一致するワイルド・カード(*
)が含まれます。XMLTable
で作成された仮想表の各行には、XPath式と一致するノードが含まれます。仮想表内の行数をカウントすることによって、要素PurchaseOrder
の子要素の数が判明します。
Oracle XML DBで提供されるXML特有の関数およびメソッドを使用すると、XMLコンテンツへのリレーショナル・アクセスを提供する、従来のリレーショナル・ビューを作成できます。これによって、Oracle Databaseには対処していてもXMLには対処していないプログラマ、ツールおよびアプリケーションでも、データベースに格納されたXMLコンテンツを操作できます。
リレーショナル・ビューでは、XPath式とXMLTable
などのSQL/XML問合せおよびアクセス関数を使用して、ビューの列とXML文書のノードとの間のマッピングを定義できます。XML文書が、CLOB
インスタンスとしてではなく、構造化(オブジェクト・リレーショナル)XML記憶域またはバイナリXML記憶域を使用して格納されている場合のみ、パフォーマンス上の理由からこの方法をお薦めします。
関連項目:
|
XMLType
表内の各文書をリレーショナル・ビューの行として公開する必要がある場合は、次の方法を使用できます。
CREATE OR REPLACE VIEW
を使用して、ビューを構成する一連の列を定義します。
XML文書内のノードを、ビューで定義されている列にマップします。このためには、SQL/XML関数XMLTable
を適切なXPath式とともに使用して、ノードを抽出します。
この方法は、XMLType
表内の文書とビュー内の行の間に、1対1 (1:1)の関係がある場合はいつでも使用できます。
例3-32では、XMLコンテンツを公開する簡単なリレーショナル・ビューpurchaseorder_master_view
の作成方法を示します。このビューには、XMLType
表purchaseorder
の行ごとに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)
XMLType
表に複数レベルで含まれているデータをリレーショナル・ビューの個別の行として公開する必要がある場合は、単一レベルの分割と同じ一般的な方法を使用し、1)ビューを構成する列の定義、および、2)列へのXMLノードのマップを行います。ただし、この場合は、分割してリレーショナル列に格納する各文書レベルにXMLTable
を適用します。
この方法は、XMLType
表内の文書とビュー内の行の間に、1対多 (1:N)関係がある場合はいつでも使用できます。
たとえば、各PurchaseOrder
要素にLineItems
要素が含まれていて、この要素に1つ以上のLineItem
要素が含まれているとします。各LineItem
要素には、Description
やItemNumber
属性などの子要素があります。このような下位レベルのデータをリレーショナル値としてアクセス可能にするには、PurchaseOrder
要素とLineItem
コレクションの両方を分割する必要があります。この分割は、いずれもXMLTable
を使用して行われます。要素PurchaseOrder
を分割すると、LineItem
要素は、XMLフラグメントが含まれている型XMLType
のリレーショナル列にマップされます。この列は次に、XMLType
への2回目のコールに渡され、リレーショナル値の複数の行として複数の部分に分割されます。
例3-33に、これを示します。この例では、XMLType
表purchaseorder
内の文書とビューの行の間に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
の各行は、XMLType
表purchaseorder
に格納されているXML文書内の各LineItem
要素に対応しています。
CREATE OR REPLACE VIEW
文では、ビューを構成する一連の列を定義します。SELECT
文は、コンテキストとしてpurchaseorder
表を関数XMLTable
に渡し、列reference
およびlineitem
を含む、仮想表p
を作成します。これらの列には、発注書のReference
およびLineItem
要素がそれぞれ含まれます。
列lineitem
にはLineItem
要素のコレクションがXMLType
インスタンスとして含まれ、各行が各LineItem
要素に対応します。これらの行は次に、2つ目のXMLTable
式に渡され、そのコンテキストとして機能します。この2つ目のXMLTable
式により、明細/項目行の仮想表が作成され、各列が要素LineItem
の様々な子孫ノードに対応します。これらの子孫の大半は属性(ItemNumber
やPart/@Id
など)です。子孫の1つはDescription
子要素です。
Reference
要素は列reference
としてビューpurchaseorder_detail_view
に含まれます。ビューpurchaseorder_detail_view
の行をビューpurchaseorder_master_view
の対応する行に結合するのに使用できる外部キーを提供します。CREATE VIEW
文の相関結合によって、ビューにアクセスするたびに、Reference
要素と、関連するLineItem
要素の間の1対多(1:N)の関係が保持されます。
この項の例では、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
の行に値がSBELL
のuserid
列が含まれている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コンテンツに対する更新操作を実行できます。更新操作では、文書のコンテンツ全体または文書の一部を置き換えることができます。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.
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に基づかないデータと基づくデータの両方に適用されます。
名前空間のサポートは、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は、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の構築に依存せずにストリーム方式で評価されます。
この項では、Oracle XML DBを使用してリレーショナル・データからXMLデータを生成する例を紹介します。
標準のSQL/XML関数を使用すると、XML文書を1つ以上生成できます。SQL/XML関数XMLQuery
は、これを行うための最も一般的な方法です。この操作に使用できるSQL/XML関数には、他に次のものがあります。
XMLElement
は、要素を作成します。
XMLAttributes
は、属性を要素に追加します。
XMLForest
は、要素のフォレストを作成します。
XMLAgg
は、要素のコレクションから単一の要素を作成します。
例3-41の問合せでは、これらの関数を使用して、表departments
、locations
、countries
、employees
および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
要素には、サブ要素のName
、Location
およびEmployeeList
も含まれます。
Name
要素に関連付けられたテキスト・ノードは、departments
表のname
列から生成されます。
Location
要素には、子要素Address
、City
、State
、Zip
および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 を使用して作成された要素の子孫でない場合にのみサポートされます。 |
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式によって、値が10
のDEPARTMENT_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文書を生成します。
W3CのXSLT勧告は、XML文書の形式を別の形式に変換する方法を指定するためのXML言語を定義します。変換には、1つのXML Schemaから別のXML Schemaへのマッピング、またはXMLからHTMLやWMLなどの他の形式へのマッピングが含まれる場合があります。
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リポジトリを使用すると、XMLコンテンツをファイル/フォルダ隠喩を使用して編成できます。これによって、URLを使用して、データベースに格納されたXML文書を一意に識別できます。これまでURLやXPath式などの構造体を使用してコンテンツを識別してきたXML開発者は、この方法の使用を検討できます。
Oracle XML DBリポジトリは、DAV標準に基づいてモデル化されています。DAV標準では、WebDAVサーバーで管理されるファイルやフォルダを示すためにリソースという用語が使用されます。リソースは、メタデータとコンテンツの組合せで構成されます。DAV仕様には、リソースごとにWebDAVサーバーが管理する一連の(システム定義の)メタデータ・プロパティ、およびDAVサーバーやDAV対応クライアントでメタデータを交換するために使用する一連のXML文書が定義されています。
Oracle XML DBリポジトリでは、あらゆる種類のコンテンツを管理できますが、コンテンツがXMLであるリソースを管理するための特別な機能と最適化機能が用意されています。
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日でセキュリティ・ガイド』を参照してください。 |
リレーショナル・データベースを使用して階層フォルダ構造を保持する場合、フォルダに対して項目を追加または削除するときに高度な同時実行性を保証することは重要な問題です。従来のファイル・システムでは、トランザクションの概念はありません。各操作(ファイルの追加、サブフォルダの作成、ファイル名の変更、ファイルの削除など)は、基本トランザクションとして処理されます。操作が完了すると、ファイル・システムのすべてのユーザーに対して変更がすぐに反映されます。
注意: データベースによって適用されるトランザクション・セマンティクスの結果として、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を最小限にすることもできます。
これは、短時間の間に複数のアプリケーションが同じディレクトリ内にファイルを生成する場合に役立ちます。たとえば、トレース・ファイルやログ・ファイルを生成する場合、印刷または電子メール配信用にスプール・ディレクトリを保持する場合などです。
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-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文書を表示する操作を示します。
Oracle XML DBリポジトリは、SQLから直接アクセスして更新できます。そのため、SQLを使用してOracle Databaseと対話できるアプリケーションまたはプログラミング言語からも、リポジトリに格納されたコンテンツにアクセスして更新できます。Oracle XML DBには、プログラムによるリソースの作成、変更および削除を可能にするメソッドが備わったPL/SQLパッケージDBMS_XDB
が含まれています。
例3-50に、PL/SQL関数DBMS_XDB.createResource
を使用して簡単なテキスト・ドキュメントのリソースを作成する方法を示します。
この項では、Oracle XML DBリポジトリのコンテンツにアクセスして更新するための機能について説明します。
リポジトリに格納されたコンテンツには、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日でセキュリティ・ガイド』を参照してください。 |
表XDB$RESOURCE
は、SQLプログラマに直接公開されていません。リポジトリのコンテンツは、2つのパブリック・ビュー(RESOURCE_VIEW
およびPATH_VIEW
)を介して公開されます。リポジトリに格納された文書のメタデータおよびコンテンツはいずれも、これらのビューを介してアクセスして更新できます。いずれのビューにも仮想列RES
が含まれます。パス表記法を使用したSQL文でドキュメントにアクセスして更新するには、RES
を使用します。ビューに対する操作では、リポジトリ内の基礎となる表を使用します。
Oracle XML DBには、リポジトリ固有のSQL関数としてexists_path
およびunder_path
という2つの関数があります。これらの関数を使用して、パスベースの述語をSQL文のWHERE
句に含めます。SQL操作では、リポジトリのフォルダ階層内におけるコンテンツの場所に基づいてリポジトリのコンテンツを選択できます。階層リポジトリ索引を使用すると、パスベースの問合せが効率的に実行されます。
XML Schemaに基づくXML文書をリポジトリに格納すると、文書のコンテンツはXML Schemaにより識別されるデフォルト表にオブジェクトとして格納されます。リポジトリには、文書に関するメタデータと、コンテンツを含むデフォルト表内の行を識別するポインタ(XMLType
のREF
)のみが含まれます。
別の種類の文書をリポジトリに格納することも可能です。XMLでない、またはXML Schemaに基づかない文書をリポジトリに格納すると、文書のコンテンツは、文書のメタデータとともにLOBに格納されます。
Oracle XML DBリポジトリはSQLを使用してアクセスおよび更新できるため、PL/SQLプロシージャをコールできるアプリケーションはすべて、このリポジトリを使用できます。すべてのSQLおよびPL/SQLリポジトリ操作はトランザクション型です。リポジトリとそのコンテンツへのアクセスは、標準的なデータベース・セキュリティ制御とリポジトリのアクセス制御リスト(ACL)両方の対象となります。
提供されているPL/SQLパッケージDBMS_XDB
、DBMS_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; /
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関数XMLTable
のXMLNAMESPACES
句を使用して定義されます。発注書XML Schemaで名前空間が定義されておらず、名前空間接頭辞をPurchaseOrder
文書のノードに適用できないため、ここでは名前空間の宣言が必要になります。
XML Schemaに基づくXML文書のコンテンツにアクセスするには、次の2つの方法があります。
XML Schemaに基づかないXML文書の場合と同様に、リソース・ドキュメントを使用してアクセスします。この方法では、RESOURCE_VIEW
を使用して、XML Schemaに基づく様々な種類のXML文書を1つのSQL文で問い合せることができます。
XML SchemaをOracle XML DBに登録したときに定義したデフォルト表の行としてアクセスします。
リソース・ドキュメントの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に格納されたコンテンツの更新および編集
Microsoft Wordなどの編集アプリケーションを使用してOracle XML DBに格納されたXML文書を更新すると、データベースは、文書の新しいコンテンツを含む入力ストリームを受け取ります。ただし、Wordなどのアプリケーションでは、Oracle XML DBは文書がどのように変更されたかを識別できません。そのため、部分的な変更は不可能です。文書全体を再度解析し、元の文書から導出されたすべてのオブジェクトを、新しいコンテンツから導出されたオブジェクトに置き換える必要があります。
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文書を更新できます。メタデータに基づくパスまたは条件が含まれた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-properties
やupdate
など)が決まります。各リポジトリ操作には、現行ユーザーがその操作の実行を許可されているかどうかを判断するために、ACLの確認が含まれています。デフォルトでは、新規のリソースはその親フォルダのACLを継承します。ただし、PL/SQLプロシージャDBMS_XDB.setACL
を使用してリソースのACLを設定することもできます。Oracle XML DBのリソースのセキュリティの詳細は、第27章「リポジトリのアクセス制御」を参照してください。
次の例で、現行ユーザーはQUINE
です。問合せでは、フォルダ/public
のリソースの数が戻されます。このフォルダには、f1
とf2
の2つのリソースのみが存在すると想定します。また、f1
のACLではread-properties
権限がQUINE
に付与されますが、f2
のACLではQUINE
に付与される権限はないと想定します。ユーザーがリソースを参照するには、そのリソースに対するread-properties
権限が必要です。QUINE
はf1
のみ参照できるため、問合せの結果は1
です。
SELECT count(*) FROM RESOURCE_VIEW r WHERE under_path(r.res, '/public') = 1; COUNT(*) -------- 1
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
には、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)
関連項目:
|
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文書です。メタデータには、CreationDate
、Creator
、Owner
、ModificationDate
、DisplayName
などの情報が含まれています。リソース・ドキュメントのコンテンツは、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.
従来のリレーショナル・データベースでは、パスベースのアクセスおよびフォルダ限定の問合せは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ファイルをリポジトリにロードすると、次の順序でイベントが発生します。
Oracle XML DBは、XML文書のルート要素を調べ、既知(登録済)のXML Schemaに関連付けられているかどうかを確認します。このとき、文書にXMLSchema-instance
名前空間の名前空間宣言が含まれているかどうかが確認され、文書に関連付けられたXML Schemaを識別するschemaLocation
属性またはnoNamespaceSchemaLocation
属性が検索されます。
文書が既知のXML Schemaに基づいている場合は、XML SchemaのメタデータがXML Schemaのキャッシュからロードされます。
XML文書は解析され、XML Schemaから導出された一連のSQLオブジェクトに分解されます。
XMLファイルから作成されたSQLオブジェクトは、XML Schemaがデータベースに登録されたときに定義されたデフォルト表に格納されます。
リソース・ドキュメントは、処理された文書ごとに作成されます。これによって、リポジトリを使用して、文書のコンテンツにアクセスできます。XML Schemaに基づくXMLType
インスタンスのリソース・ドキュメントには、XMLRef
要素が含まれています。この要素には、リソースに関連付けられたコンテンツが含まれるデフォルト表内の行を検索するときに使用できるXMLType
のREF
が含まれます。
Oracle XML DBに組み込まれたHTTPサーバーでは、ブラウザを使用して、Oracle XML DBリポジトリに格納された文書にアクセスできます。リソースにはXMLType
表またはビューの行に対するREF
を含めることができるため、パスを使用してこのようなコンテンツにアクセスできます。
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など読みやすい形式で表示できます。
スタイルシート処理を開始するには、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
に設定します。
図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-8に、HTML文書として表示されたdepartments
表を示します。コーディングは不要で、これを表示するためには、SQL/XML関数に基づくXMLType
ビュー、業界標準のXSLスタイルシートおよびDBUri
サーブレットのみが必要です。
脚注の凡例
脚注1: XML Schemaに基づくデータのXMLType
記憶域モデルは、参照するXML Schemaの登録時に指定したものです。登録時に記憶域モデルを指定しなかった場合は、バイナリXML記憶域が使用されます。maintainOrder = "false"
を使用すると、Ordered Collectionでなく、Unordered Collectionが使用されます。XMLデータの場合、ドキュメント内の順序を保持するために、Ordered Collection(maintainOrder = "true"
)を使用することをお薦めします。デフォルトでは、属性maintainOrder
はtrue
です。