この章では、Oracle XML DBでのXQuery言語の使用方法を説明します。XQuery言語でのOracle XML DBサポート、たとえばSQL/XML関数XMLQuery
およびXMLTable
、それにSQL*Plus XQUERY
コマンドについて説明します。
この章の内容は次のとおりです。
Oracle XML DBのXQuery言語サポートは、SQL/XML関数XMLQuery
およびXMLTable
のネイティブ実装により提供されています。便宜性の観点から、SQL*PlusのコマンドXQUERY
も用意されており、XQuery式を直接入力することができます。実質的に、このコマンドにより、SQL*PlusはXQueryコマンドライン・インタプリタになります。
Oracle XML DBは、SQL/XML関数XMLQuery
、XMLTable
、XMLExists
およびXMLCast
に引数として渡されるXQuery式をコンパイルします。このコンパイルにより、SQL問合せブロックと、SQL/XML関数とXPath関数を使用する演算子ツリーが作成されます。XMLQuery
、XMLTable
、XMLExists
またはXMLCast
を含むSQL文は一括してコンパイルおよび最適化され、リレーショナル・データベースとXQuery特有の最適化テクノロジの両方を活用します。使用するXML記憶域と索引付けメソッドにより、XPath関数をさらに最適化することができます。結果として生じる最適化された演算子ツリーは、ストリーム方式で実行されます。
関連項目:
|
Oracle XML DBはXQuery言語の最新バージョンの仕様、W3C XQuery 1.0勧告をサポートしています。このセクションでは、XQuery言語の簡単な概要を示します。詳細は、XQuery言語に関する最新の書籍や、http://www.w3c.org
から入手できる、XQueryを定義している標準に関する文書を参照してください。
XQuery 1.0はXMLデータの問合せのために設計されたW3C言語です。多くの点でSQLに類似していますが、SQLが単に構造化されたリレーショナル・データを問い合せるために設計されているのに対し、XQueryは、様々なデータ・ソースの半構造化されたXMLデータを問い合せるために特に設計されています。XQueryは、XMLデータがあれば、Webサービスからアクセスできるデータベース表に格納されているか、他の方法でその場で作成されるかに関係なく、XMLデータを問い合せるためにいつでも使用できます。XMLデータの問合せの他に、XQueryはXMLデータの構成にも使用できます。この点で、XQueryはXSLTやその他のSQL/XMLパブリッシング関数(XMLElement
など)の代用として使用できます。
XQueryは、XML Information Set (Infoset)データ・モデルとXML Schema型体系を統合した、Post-Schema-Validation Infoset (PSVI)データ・モデルに基づいています。XQueryではシーケンスに基づく新しいデータ・モデルが定義されています。各XQuery式の結果がシーケンスです。XQueryは常にシーケンスの操作に関わります。このためXQueryは集合操作言語に類似しています。ただしシーケンスは順序付けされていて、重複項目を含むことができる点が異なります。XQueryシーケンスが他の言語のシーケンスと異なる点は、ネストされたXQueryシーケンスは実際の効果において常にフラット化されるという点です。
多くの場合、シーケンスを順序のないものとして処理することにより最適化を促進できます。ただしそれは可能な場合に限られ、ユーザーの責任となります。この順序なしモードは、ネストされた反復(for
)の処理で順序を結合する場合や、XPath式を処理する場合に適用できます(たとえば/a/b
では、一致するb
要素は文書順序に関係なく処理できます)。
XQueryシーケンスはゼロ個以上の項目から構成されています。項目は、アトム型(スカラー)の値またはXMLノードです。項目は、XML Schemaの型に基づくリッチ型体系を使用して型指定されます。この型体系は、ブール、数値、および文字列といった単純なスカラー型に制限されていたXPath 1.0から大きく変更された部分です。
XQueryは関数言語です。このため、評価され、値(XQueryではシーケンス)を戻す、可能な式の集合からなります。XQueryは関数言語なので、通常は参照が透過的です。同じコンテキストで評価された同じ式は同じ値を戻します。
こうした数学的長所の例外には、次のものがあります。
外部環境との相互作用から値を導出するXQuery式。たとえば、fn:current-time(...)
またはfn:doc(...)
といった式は常に同じ値を戻すとはかぎりません。これは、それらの式が、変化する外部の条件に依存しているためです(時刻の変化、ターゲット文書のコンテンツの変化)。
fn:doc
のような場合には、XQueryは単一の問合せの実行の内部で参照が透過的なものと定義されます。単一の問合せの内部では、同じ引数を伴うfn:doc
の呼出しは、同じ文書を結果とします。
個別のXQuery言語の実装に依存するものとして定義されているXQuery式。そうした式の評価結果は、実装に応じて異なる場合があります。関数fn:doc
は、本質的に実装により定義される関数の例です。
参照の透過性は、XQuery変数にも適用されます。同じコンテキストでの同じ変数は同じ値を持ちます。関数言語はこの点で、数学で言う形式主義に似ており、手続き型、または命令型のプログラミング言語とは異なっています。手続き型言語の変数は、実際にはメモリー位置の名前で、現在の値や状態を持っており、任意の時点におけるその内容により表現されます。XQueryなど宣言型言語における変数は、実際には静的な値の名前です。
XQuery式では大/小文字が区別されます。式には次のものが含まれます。
1次式: リテラル、変数、または関数アプリケーション。変数名は、たとえば$foo
のように、ドル記号($
)で始まります。リテラルには、数値、数値、文字、または実体参照。
XPath式: 任意のXPath式。XPath 2.0標準はXQueryのサブセットになります。
FLWOR式: 最も重要なXQuery式で、次の要素を順番に並べたもので構成されています。FLWORという名もそれに由来しています。for
、let
、where
、order by
、return
。
XQueryシーケンス: カンマ(,
)コンストラクタはシーケンスを作成します。union
やintersect
といったシーケンス操作関数も使用できます。XQueryシーケンスはすべて、事実上フラットです。ネストされたシーケンスは、フラット化された同等のものとして処理されます。このため、たとえば(1, 2, (3, 4, (5), 6), 7)
は(1, 2, 3, 4, 5, 6, 7)
として処理されます。(42)
などの単一シーケンスは、大部分のXQueryコンテキストで、単一項目42
と同じ動作をします。前述のように、任意のXQuery式の結果はシーケンスです。
直接(リテラル)構成: XML要素と属性の構文により、要素と属性が自動的に構成されます。構文に表記したとおりに使用されることになります。たとえば、XQuery式<a>33</a>
により、XML要素<a>33</a>
が構成されます。
計算による(動的)構成: 計算された値を使用して、実行時にXMLデータを構成できます。たとえば、次のXQuery式によりこのXMLデータ<foo toto="5"><bar>tata titi</bar> why? </foo>
が構成されます。
<foo>attribute toto {2+3}, element bar {"tata", "titi"}, text {" why? "}</foo>
この例では、要素foo
が直接構成で、他の部分の構成は計算されたものです。実践では、計算されるコンストラクタの引数はリテラル(toto
、"tata"
など)ではなく式(2+3
など)で、評価されます。要素や属性コンストラクタの名前と値引数は、どちらも計算できます。中カッコ({
, }
)は、XQuery式を評価対象外にするのに使用します。
条件式: 通常どおりですが、式の各部分が任意の式になることに注意してください。たとえば、この条件式では、任意のXQuery式が各部分式(something
、somethingElse
、expression1
、およびexpression2
)に入ります。
if (something < somethingElse) then expression1 else expression2
数式、リレーショナル式 – 通常どおりですが、各リレーショナル式が(ブール脚注1)値を戻すことに注意してください。次に例を示します。
2 + 3 42 < $a + 5 (1, 4) = (1, 2) 5 > 3 eq true()
量化式: 全称(every
)および存在(some
)関数を使用してFLWOR式を簡単に使用できる場合があります。次に例を示します。
every $foo in doc("bar.xml")//Whatever satisfies $foo/@bar > 42 some $toto in (42, 5), $titi in (123, 29, 5) satisfies $toto = $titi
正規表現: XQueryの正規表現はXML Schema1.0およびPerlに基づいています。(「XQueryの関数と演算子のサポート」を参照)
型表現: XQuery型を表現するXQuery式。たとえば、item()
、node()
、attribute()
、element()
、document-node()
、namespace()
、text()
、xs:integer
、xs:string
。脚注 2
型表現は、次のような出現インジケータを持てます。?
(オプション。0回または1回)、*
(0回以上)、+
(1回以上)。たとえば、document-node(element())*
、item()+
、attribute()?
。
XQueryには、型と組み合せて使用する演算子もあります。cast as
、castable as
、treat as
、instance
の、typeswitch
、およびvalidate
などです。たとえば、"42" cast as xs:integer
は、値が整数の2である式です。(厳密には、値が型を表現していないので、これは型表現ではありません)。
XQuery一般について考えた場合、FLWOR式には多くの学習事項があります。この項の説明は簡単な概要にすぎません。
FLWORはXQueryで最も一般的な式構文です。FLWOR(「フラワー」と読みます)は、for
、let
、where
、order by
、およびreturn
を表しています。FLWOR式には1つ以上のfor
またはlet
句と、1つのreturn
句を持ちます。1つのwhere
およびorder by
句がオプションです。
for
: 1つ以上の変数を任意の値に順にバインドします。つまり、各変数に対し反復を行いますが、変数を各回の反復で別の値にバインドします。
各回の反復で、変数は出現する順にバインドされ、for
リストで$later
の前にリストされた変数$earlier
の値が、変数$later
のバインドで使用されます。たとえば、次の式は、2回目の反復で$i
を4
にバインドし、$j
を6
(2+4)にバインドします。
for $i in (3, 4), $j in ($i, 2+$i)
let
: 1つ以上の変数をバインドします。
for
と同様、let
でも、let
のバインディング・リストで先にリストされている別の変数を使用して(またはfor
やlet
で囲むことにより)、変数を計算した値にバインドできます。たとえば、次の式は$j
を5
(3+2)にバインドします。
let $i := 3, $j := $i + 2
where
: for
およびlet
の変数バインディングを特定の条件に応じてフィルタします。SQLのWHERE
句に類似しています。
order by
: where
フィルタリングの結果をソートします。
return
: 順序付けとフィルタリングがされた値を構成します。これがFLWOR式の最終的な結果です。フラット化されたシーケンスになります。
式for
とlet
は、SQLのFROM
句に対して同じように機能します。式where
は、SQLのWHERE
句と同じように機能し、式order by
はSQLのORDER BY
と似ています。式return
は、SQLのSELECT
に似ています。両方の言語で名前が共通している2つのキーワード(where
、order by
)を除いて、FLWOR句の順序はSQL句の順序と反対ですが、対応する句の意味は非常に類似しています。
FLWOR式(order by
を含む)の使用は、文書の順序と異なる順序でXQueryシーケンスを構成する唯一の方法です。
SQL/XML関数XMLQuery
、XMLTable
、XMLExists
、XMLCast
は、SQL/XML標準により、SQL言語とXQuery言語の一般インタフェースとして定義されています。他のSQL/XML関数と同様、これらの関数を使用すると、SQLとXML、両方の強力な機能と柔軟性を活用できます。これらの関数を使用すると、リレーショナル・データを使用したXMLデータの構成、XML同様のリレーショナル・データに対する問合せ、およびXMLデータからのリレーショナル・データの構成が可能です。
SQL関数XMLExists
およびXMLCast
については、このマニュアルの別の項で説明します。この項では、関数XMLQuery
とXMLTable
について説明しますが、本章の例の大半はXMLExists
およびXMLCast
も使用します。一般的な使用方法は次のとおりです。
XMLQuery
とXMLCast
は通常、SELECT
リストで使用します。
XMLTable
は一般的にSQLのFROM
句で使用します。
XMLExists
は通常、SQLのWHERE
句で使用します。
XMLQuery
とXMLTable
の両方がXQuery式を評価します。XQuery言語では、式は常に項目のシーケンスを戻します。関数XMLQuery
はこのシーケンスの項目を集計し、単一のXML文書または断片を戻します。関数XMLTable
は、XQueryシーケンスからの1つの項目を各行に含むSQL表を戻します。
関連項目:
|
SQL/XML関数XMLQuery
を使用して、XMLデータの構成や問合せができます。この関数は引数としてXQuery式、文字列としてリテラル、そしてオプションで、XQueryコンテキスト項目をSQL式として取ります。コンテキスト項目は、XQuery式を評価する際のXPathコンテキストを確立します。この他に、XMLQuery
は、XQuery式の評価の際にXQuery変数にバインドされた値を持つ任意の数のSQL式を引数として受け取ります。関数はXQuery式の評価結果をXMLType
インスタンスとして戻します。
XML_passing_clause::=
XQuery_string
は完結したXQuery式で、プロローグをリテラル文字列として含む場合があります。
XML_passing_clause
はキーワードPASSING
に1つ以上のSQL式(expr
)を続けたもので、それぞれXMLType
インスタンスまたはSQLスカラー・データ型の(つまり、オブジェクト・データ型でもコレクション・データ型でもない)インスタンスを戻します。それぞれの式(expr
)は、適切にキャストされた表またはビューの列の値、PL/SQL変数、バインド変数のいずれかになります。1つを除いてすべての式では、その後にAS
およびXQuery identifier
が続いている必要があります。それぞれのexpr
の評価結果は、対応するidentifier
にバインドされ、続いてXQuery_string
が評価されます。AS
句に続いていないexpr
があった場合、そのexpr
の評価結果は、XQuery_string
を評価する際のコンテキスト項目として使用されます。Oracle XML DBではBY VALUE
を渡すことはできますが、BY REFERENCE
は渡せないため、BY VALUE
句は暗黙的で、省略可能です。
RETURNING
CONTENT
は、XMLQuery
のアプリケーションが戻す値が、パラメータ化されたXML型XML(CONTENT)
のインスタンスであり、パラメータ化された型XML(SEQUENCE)
のインスタンスではないことを示します。これは拡張Infosetデータ・モデルに準拠した文書フラグメントです。このため、任意の数の子を持つ単一の文書ノードとなります。子はそれぞれ任意のXMLノード型を取ることができ、特に、テキスト・ノードになることが可能です。
SQL/XML関数XMLQuery
でOracle XML DBがサポートするのはRETURNING CONTENT
句のみです。RETURNING SEQUENCE
句はサポートしていません。
XMLType
の列、表、またはビューは、関数XMLQuery
のコンテキスト項目引数として渡すことができます。例として、例5-8を参照してください。
リレーショナル表やビューに対して、XMLデータのときのように最初にSQL/XMLビューを作成する必要なく問合せを実行するには、XQuery関数fn:collection
をXQuery式内で使用し、URIスキーム名oradb
を使用するURIを、データのデータベースの場所とともに引数として引き渡します。「URIスキームoradb: XQueryを使用した表またはビュー・データの問合せ」を参照してください。
注意: Oracle Database 11gリリース2より前のリリースでは、一部のユーザーは一部の処理の実行にOracle SQL関数extract およびextractValue を使用していました。これらの処理は、SQL/XML関数XMLQuery およびXMLCast を使用するとより効率的に実行できます。SQL関数extract およびextractValue は、Oracle Database 11gリリース2で非推奨になりました。 |
関連項目:
|
SQL/XML関数XMLTable
は、XQuery式の評価結果を新規の仮想表に対するリレーショナル行と列に分解します。その仮想表は、既存のデータベース表に挿入したり、SQLを使用して(join式など)問い合せたりできます(例5-9を参照)。SQLのFROM
句でXMLTable
を使用します。
XML_namespaces_clause::=
XMLTABLE_options::=
XML_passing_clause::=
XML_table_column::=
XQuery_string
は完結したXQuery式で、プロローグをリテラル文字列として含む場合があります。式の値は XMLTable
関数への入力となります。つまり、このXQueryの結果が分解されリレーショナル・データとして格納されます。
オプションのXMLNAMESPACES
句にはXML名前空間宣言が含まれており、XML_table_column
のPATH
句で、XQuery_string
およびXPath式により参照されます。
XML_passing_clause
はキーワードPASSING
に1つ以上のSQL式(expr
)を続けたもので、それぞれXMLType
インスタンスまたはSQLスカラー・データ型の(つまり、オブジェクト・データ型でもコレクション・データ型でもない)インスタンスを戻します。それぞれの式(expr
)は、適切にキャストされた表またはビューの列の値、PL/SQL変数、バインド変数のいずれかになります。1つを除いてすべての式では、その後にAS
およびXQuery identifier
が続いている必要があります。それぞれのexpr
の評価結果は、対応するidentifier
にバインドされ、続いてXQuery_string
が評価されます。AS
句に続いていないexpr
があった場合、そのexpr
の評価結果は、XQuery_string
を評価する際のコンテキスト項目として使用されます。Oracle XML DBではBY VALUE
を渡すことはできますが、BY REFERENCE
は渡せないため、BY VALUE
句は暗黙的で、省略可能です。
オプションのCOLUMNS
句は、XMLTable
により作成される仮想表の列を定義します。
COLUMNS
句を省略した場合、XMLTable
は、COLUMN_VALUE
という名前で単独のXMLType
疑似列を戻します。
FOR ORDINALITY
は、column
が生成される行数の列になることを示します(SQLデータ型NUMBER
)。最大で1個のFOR ORDINALITY
句がある必要があります。
FOR ORDINALITY
列を除き、生成された各列に列のデータ型を指定する必要があります。XMLType
または任意のSQLデータ型(構文の説明でdatatype
と呼ばれる)を指定できます。
オプションのPATH
句は、XQuery式string
により扱われたXQueryの結果の一部がcolumn
コンテンツの一部として使用されることを示しています。複数のPATH
句を使用してXQueryの結果を異なる仮想表の列に分割できます。
PATH
を省略した場合は、XQuery式がcolumn
であるものと仮定されます。たとえば、次の2つの式は等価です。
XMLTable(... COLUMNS foo) XMLTable(... COLUMNS foo PATH 'FOO')
XQuery式string
はXQuery_string
に対して相対的であるため、相対パスの表記にする必要があります。
オプションのDEFAULT
句は、PATH
式の結果が空のシーケンス(またはNULL
)になる場合に使用する値を指定します。そのexpr
は、評価されてデフォルト値を生成するXQuery式です。
関連項目:
|
注意: Oracle Database 11gリリース2より前のリリースでは、一部のユーザーは一部の処理の実行に、SQLTABLE コレクション式でOracle SQL関数XMLSequence (TABLE(XMLSequence(...)) )を使用していました。これらの処理は、SQL/XML関数XMLTable を使用するとより効率的に実行できます。関数XMLSequence は、Oracle Database 11gリリース2で非推奨になりました。
SQL |
SQL/XML生成関数またはXSLTを使用して実行される処理には、XQueryを使用して実行できるものが多く、両者の用途は多くの点で一致しています。あるタスクを実行する際にどのツールを使用するかは、様々な考慮事項に基づいて決定されるものであり、その考慮事項の多くはOracle Database以外に関連するものです。このような一般的な問題については、外部のドキュメントを参照してください。
一般的には、XMLデータに主眼を置いている場合はXQueryが使用され、リレーショナル・データに主眼を置いている場合はSQL/XML生成関数(XMLElement
、XMLAgg
など)が使用されます。
他の条件が同じであれば、既存のXML文書から抽出されたフラグメントに基づいて問合せによってXML文書を構成する場合は通常、リレーショナル・データからスカラー値を抽出し、SQL/XML生成関数を使用して目的のXMLデータを構成するよりも、通常はXQueryのFLOWR式が単純になります(そのためコードのメンテナンスも簡単になります)。一方、既存のリレーショナル・データに基づいて問合せによってXML文書を構成する場合は、通常、SQL/XML生成関数を使用する方が適しています。
Oracle XML DBに関しては、SQL/XML生成関数を使用しても、XMLQuery
およびXMLTable
を使用しても、期待できるパフォーマンスは、同じ一般的なレベルです。これは、いずれも最適化のリライト対象になります。
次の名前空間と接頭辞は、Oracle XML DBでXQueryとともに使用するように事前定義されています。
表5-1 事前定義の名前空間と接頭辞
接頭辞 | 名前空間 | 説明 |
---|---|---|
|
|
Oracle XML DB名前空間 |
|
|
XPathのローカル関数宣言名前空間 |
|
|
XPath関数名前空間 |
|
|
XML名前空間 |
|
|
XML Schema名前空間 |
|
|
XML Schemaインスタンス名前空間 |
これらの接頭辞は、あらかじめXQuery式プロローグで宣言しなくてもXQuery式で使用できます。また、xml
以外は、すべてプロローグ内で再定義できます。ora
以外の接頭辞はすべて、XQuery標準で事前定義されています。
XQuery関数fn:doc
とfn:collection
を使用して、Oracle XML DBリポジトリのリソースに対して問い合せることができます — 「XQueryを使用したOracle XML DBリポジトリ内でのXMLデータの問合せ」を参照してください。この項では、XQuery関数fn:collection
を使用した、データベースの表およびビュー内のデータの問合せについて説明します。
これを行うには、問い合せる表またはビューを指定する、関数fn:collection
のURI引数を渡します。Oracle URIスキーマoradb
によりこの使用が識別されます。これがないと、引数はリポジトリの場所として扱われます。
問い合せる表またはビューは、リレーショナルまたはXMLType
型のどちらでもかまいません。リレーショナルの場合は、データはその場で変換され、XMLとして扱われます。fn:collection
によって戻される結果は、常にXQueryシーケンスです。
XMLType
の表については、fn:collection
によって戻される各XML文書のルート要素は、表のXML文書のルート要素と同じです。
リレーショナルの表の場合、fn:collection
によって戻される各XML文書のルート要素はROW
です。ROW
要素の子は、表の列と同じ名前(大文字)を持つ要素です。子要素の内容は、列のデータに一致します。列の型がXMLType
の場合は内容はXML要素で、それ以外の場合(列はスカラー型)は内容はxs:string
型です。
fn:collection
に引き渡されるURI要素の形式は、次のとおりです。
データベース・スキーマDB-SCHEMA
内のXMLType
またはリレーショナルの表あるいはビューTABLE
の場合
oradb:/DB-SCHEMA/TABLE/
TABLE
がバブリック・シノニムか、TABLE
が現在ログイン中のデータベース・ユーザーがアクセス可能な表またはビューの場合、DB-SCHEMA
にPUBLIC
を使用できます。
リレーショナルの表またはビュー内のXMLType
列の場合
oradb:/DB-SCHEMA/REL-TABLE/ROWPRED/X-COL
REL-TABLE
はリレーショナル表またはビューで、PRED
はXMLType
列と関係しないXPath述語です。X-COL
はREL-TABLE
のXMLType
列です。PRED
はオプションで、DB-SCHEMA
、REL-TABLE
およびX-COL
は必須です。
オプションのXPath述語PRED
は、次の条件を満たす必要があります。
XMLType
列が一切関係しない。
一般的な同等の結合(and
)と分離(or
)および不等の比較(=
、!=
、>
、<
、>=
、<=
)のみが関係している。
それぞれの比較演算について、REL-TABLE
の両側の名前(XML以外)列、またはある列と他方のような一方の名前が、表5-2で指定された正しい型の値である。他の型を使用すると、エラーが発生します。
表5-2 oradb式: 比較用の列の型
リレーショナルの列の型 | XQuery値の型 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
たとえば、このXQuery式は、表oe.warehouses
のXMLType
列warehouse_spec
にあって、列warehouse_id
の値が6より小さい行のすべてのXML文書を表します。
fn:collection('oradb:/OE/WAREHOUSES/ROW[WAREHOUSE_ID < 6]/WAREHOUSE_SPEC')
Oracle XML DBには、W3C標準に用意されているものの他に、いくつかのXQuery関数が追加されています。それらの追加関数はOracle XML DB名前空間、http://xmlns.oracle.com/xdb
にあります。この名前空間は事前定義の接頭辞ora
を使用します。この項ではこれらのOracle拡張関数を説明します。
ora:contains構文
ora:contains (input_text, text_query [, policy_name] [, policy_owner])
XQueryおよびXPath関数ora:contains
は、SQL/XML関数XMLQuery
、XMLTable
またはXMLExists
へのコールのXQuery式内で使用できます。これは、全文述語を伴う構成検索を制限する場合に使用されます。関数ora:contains
はinput_text
がtext_query
と一致した場合は正の整数を戻し(数字が大きいほど、一致の関連性は高くなります)、一致しない場合はゼロを戻します。XQuery式内部で使用される場合(XPath式のみでなく)、XQueryの戻り型はxs:integer()
です。XQuery式外部のXPath式で使用される場合、XPathの戻り型はnumber
です。
引数input_text
は単一のテキスト・ノードまたは属性に対して評価される必要があります。ora:contains
におけるtext_query
の構文と意味論は、いくつかの制限を伴う他はcontains
におけるtext_query
と同一です。
ora:matches構文
ora:matches (target_string, match_pattern [, match_parameter])
XQuery関数ora:matches
を使用すると、正規表現を使用して文字列内のテキストを検索できます。target_string
引数が正規表現match_pattern
引数に一致していればtrue()
を、それ以外の場合はfalse()
を戻します。target_string
が空のシーケンスの場合はfalse()
を戻します。オプションの引数match_parameter
は、検索文字列を修飾するコードで、大文字/小文字の区別などを指定できます。
XQuery関数ora:matches
の動作はSQL条件REGEXP_LIKE
と同じですが、引数の型はSQLデータ型ではなくXQuery型です。引数の型は次のとおりです。
target_string
– xs:string?
脚注3
match_pattern
- xs:string
match_parameter
- xs:string
関連項目: SQL条件REGEXP_LIKE の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
ora:replace構文
ora:replace (target_string, match_pattern, replace_string [, match_parameter])
XQuery関数ora:replace
を使用すると、正規表現を使用して文字列内のテキストを置換することができます。target_string
内にある正規表現match_pattern
が出現するたびに、replace_string
に置換されます。置換の結果得られる新しい文字列を戻します。target_string
が空のシーケンスの場合は、空の文字列(""
)を戻します。オプションの引数match_parameter
は、検索文字列を修飾するコードで、大文字/小文字の区別などを指定できます。
XQuery関数ora:replace
の動作はSQL関数regexp_replace
と同じですが、引数の型はSQLデータ型ではなくXQuery型です。引数の型は次のとおりです。
target_string
– xs:string?
脚注4
match_pattern
- xs:string
replace_string
- xs:string
match_parameter
- xs:string
さらにora:replace
は引数replace_string
を必要とし(regexp_replace
ではオプション)、位置や出現回数を表す引数は使用しません。検索は最初の文字から開始され、すべての出現箇所が置換されます。
関連項目: SQL関数regexp_replace の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
ora:sqrt構文
ora:sqrt (number)
XQuery関数ora:sqrt
は、数値引数の平方根を戻します。引数はXQuery型xs:decimal
、xs:float
、またはxs:double
のいずれかです。戻り値のXQuery型は引数と同じです。
ora:tokenize構文
ora:tokenize (target_string, match_pattern [, match_parameter])
XQuery関数ora:tokenize
では、正規表現を使用して入力文字列target_string
を文字列のシーケンスに分割できます。正規表現match_pattern
と一致する部分文字列はそれぞれ、分割位置を示すセパレータとして扱われます。
トークンのシーケンスは、型xs:string*
のXQuery値(xs:string
値のシーケンス)として戻されます。target_string
が空のシーケンスの場合は、それが戻されます。オプションの引数match_parameter
は、検索文字列を修飾するコードで、大文字/小文字の区別などを指定できます。
引数の型は次のとおりです。
target_string
– xs:string?
脚注5
match_pattern
- xs:string
match_parameter
- xs:string
W3CのXQuery仕様では、実装により定義された拡張式を実装で提供できます。XQuery拡張式は、カッコ({
、 }
)で囲まれたXQuery式で、実装で定義されたプラグマが接頭辞になります。
Oracle実装では、この項で説明するプラグマが提供されます。ここに記載したプラグマ以外のプラグマは認識されません。その他のプラグマ、すなわち不正なプラグマ・コンテンツを持つプラグマ(例: (#ora:view_on_null something_else #)
)を使用すると、エラーが発生します。
ora:view_on_null
の例では、null_test
表にVARCHAR2(10)
型の列a
とb
があり、列b
(a
ではない)が空であるとします。
(#ora:defaultTable #
) – リポジトリ・データの格納に使用されるデフォルトの表を指定します。これを使用して、Query関数fn:doc
またはfn:collection
を使用するリポジトリ問合せのパフォーマンスを向上させます。「Oracle XQueryプラグマora:defaultTableの使用」を参照してください。
(#ora:invalid_path empty #)
– 無効なXPath式のターゲットとなるノードがある場合、それが存在しないかのように処理します。次に例を示します。
SELECT XMLQuery('(#ora:invalid_path empty #) {exists($p/PurchaseOrder//NotInTheSchema)}' PASSING OBJECT_VALUE AS "p" RETURNING CONTENT) FROM oe.purchaseorder p;
表oe.purchaseorder
のXML Schemaでは、NotInTheSchema
のようなノードは、PurchaseOrder
ノードの子孫とし使用できません。プラグマがない場合、このような無効なXPath式を使用するとエラーが発生します。しかし、プラグマを使用すると、コール元のコンテキストは、XPath式にターゲット・ノードがないかのように動作します。この例では、コール元のコンテキストはXQuery関数exists
で、空のノード・シーケンスが渡されると、XQueryのブール値false
を戻します。(この例ではXQuery関数exists
は動作を説明するためのみに使用されています。プラグマは関数exists
に特に関連付けられていません)。
(#ora:view_on_null empty #)
– XQuery関数fn:collection
は、それぞれのNULL
列に対して空のXML要素を戻します。たとえば、次の問合せでは、<ROW><A>x</A>
<B></B>
</ROW>
が戻されます。
SELECT XMLQuery('(#ora:view_on_null empty #)
{for $i in fn:collection("oradb:/PUBLIC/NULL_TEST")/ROW
return $i}'
RETURNING CONTENT)
FROM DUAL;
(#ora:view_on_null null #)
– XQuery関数fn:collection
は、NULL
列には要素を戻しません。たとえば、次の問合せでは、<ROW><A>x</A></ROW>
が戻されます。
SELECT XMLQuery('(#ora:view_on_null null #)
{for $i in fn:collection("oradb:/PUBLIC/NULL_TEST")/ROW
return $i}'
RETURNING CONTENT)
FROM DUAL;
(#ora:xq_proc #)
– プラグマに続くXQuery式内のXQueryプロシージャのコールを最適化しないでください。かわりに機能上の評価を使用します。
これは、SQLヒント/*+ NO_XML_QUERY_REWRITE */
と同じ効果がありますが、プラグマの範囲は後に続くXQuery式のみです(SQL文全体ではありません)。
(#ora:xq_qry #)
– プラグマに続くXQuery式を最適化してみてください。つまり、もし可能な場合は、機能面で評価しないでください。
ora:xq_proc
とora:xq_qry
の両方の使用例として、次の問合せでは、XMLQuery
に対するXQuery式の引数は、一般的に機能面で評価されますが、プラグマora:xq_qry
の後に続くfn:collection
部分式は可能なかぎり最適化されます。
SELECT XMLQuery('(#ora:xq_proc#) (: Do not optimize the XQuery expression :) {for $i in (#ora:xq_qry#) (: Optimize this subexpression :) {fn:collection("oradb:/HR/REGIONS")}, $j in (#ora:xq_qry#) (: Optimize this subexpression :) {fn:collection("oradb:/HR/COUNTRIES")} where $i/ROW/REGION_ID = $j/ROW/REGION_ID and $i/ROW/REGION_NAME = $regionname return $j}' PASSING CAST('®ION' AS VARCHAR2(40)) AS "regionname" RETURNING CONTENT) AS asian_countries FROM DUAL;
XQueryは非常に汎用性と表現力に富む言語で、SQL/XML関数XMLQuery
、XMLTable
およびXMLExists
により、それらの表現力と計算力がSQLの同様の長所と組み合されます。この項では、これら2つのSQL/XML関数でできることについて説明します。XMLExists
の詳細は、「XMLEXISTS SQL/XML関数」を参照してください。
Oracle XML DBでは、通常は次のようにXQueryを使用します。ここでの例は、それらの使用方法の違いを示すように構成されています。
Oracle XML DBリポジトリ内でXMLデータを問い合せる。
リレーショナル表またはビューを、XMLデータと同様に問い合せる。これを実行するには、Oracle XQuery関数fn:collection
を使用して、URIスキーム名oradb
を使用するURIを、引数としてデータのデータベースの場所とともに引き渡します。
「XQueryを使用した表またはビュー・データの問合せ」を参照してください。
XMLType
リレーショナル・データを問い合せ、場合により関数XMLTable
を使用して結果のXMLをリレーショナル・データに分解します。
「XQueryのXMLTypeデータとの使用」を参照してください。
例5-1は、この章の他の例の一部で使用するOracle XML DBリポジトリ・リソースを作成します。
例5-1 例で使用するリソースの作成
DECLARE res BOOLEAN; empsxmlstring VARCHAR2(300):= '<?xml version="1.0"?> <emps> <emp empno="1" deptno="10" ename="John" salary="21000"/> <emp empno="2" deptno="10" ename="Jack" salary="310000"/> <emp empno="3" deptno="20" ename="Jill" salary="100001"/> </emps>'; empsxmlnsstring VARCHAR2(300):= '<?xml version="1.0"?> <emps xmlns="http://example.com"> <emp empno="1" deptno="10" ename="John" salary="21000"/> <emp empno="2" deptno="10" ename="Jack" salary="310000"/> <emp empno="3" deptno="20" ename="Jill" salary="100001"/> </emps>'; deptsxmlstring VARCHAR2(300):= '<?xml version="1.0"?> <depts> <dept deptno="10" dname="Administration"/> <dept deptno="20" dname="Marketing"/> <dept deptno="30" dname="Purchasing"/> </depts>'; BEGIN res := DBMS_XDB.createResource('/public/emps.xml', empsxmlstring); res := DBMS_XDB.createResource('/public/empsns.xml', empsxmlnsstring); res := DBMS_XDB.createResource('/public/depts.xml', deptsxmlstring); END; /
重要なことは、XQueryが汎用のシーケンス操作言語であるということです。式や結果は、XMLデータでなくてもかまいません。XQueryシーケンスは数値、文字列、ブール値、日付など任意のXQuery型の項目と、様々な型のXMLノード(document-node()
、element()
、attribute()
、text()
、namespace()
など)を含むことができます。例5-2に例を示します。
例5-2 様々な型の項目シーケンスに適用されるXMLQuery
SELECT XMLQuery('(1, 2 + 3, "a", 100 to 102, <A>33</A>)' RETURNING CONTENT) AS output FROM DUAL; OUTPUT -------------------------- 1 5 a 100 101 102<A>33</A> 1 row selected.
例5-2では、SQL/XML関数XMLQuery
を、異なる様々な種類の項目を含むXQueryシーケンスに適用します。
整数リテラル: 1
算術式: 2 + 3
文字列リテラル: "a"
整数のシーケンス: 100 to 102
構成されたXML要素ノード: <A>33</A>
例5-2は、カンマ演算子(,
)とカッコ((
、)
)を使用してグループ化したシーケンスの構成も示しています。
シーケンス式100 to 102
の評価結果はシーケンス(100, 101, 102)
なので、XMLQuery
の引数は、ネストされたシーケンスを含むシーケンスです。シーケンス引数は、XQueryシーケンスと同様、自動的にフラット化されます。実際の引数は、(1, 5, "a", 100, 101, 102, <A>33</A>)
となります。
この項では、XQueryとXMLデータをOracle XML DBリポジトリとともに使用する例を紹介します。XQuery関数fn:doc
とfn:collection
は、それぞれリポジトリ内のファイルおよびフォルダのリソースを問い合せるときに使用します。この項の例では、XQuery関数fn:doc
を使用してXMLデータを含むリポジトリ・ファイルを取得し、FLWOR式の句for
およびlet
を使用してXQuery変数をそのデータの部分にバインドしています。
例5-3は、Oracle XML DBリポジトリ内の2つのXML文書リソース、/public/emps.xml
および/public/depts.xml
を問い合せます。fn:doc
の使用法および可能なFLWOR式のそれぞれの句を説明しています。
例5-3 for、let、order by、where、およびreturnを使用するFLOWR式
SELECT XMLQuery('for $e in doc("/public/emps.xml")/emps/emp let $d := doc("/public/depts.xml")//dept[@deptno = $e/@deptno]/@dname where $e/@salary > 100000 order by $e/@empno return <emp ename="{$e/@ename}" dept="{$d}"/>' RETURNING CONTENT) FROM DUAL; XMLQUERY('FOR$EINDOC("/PUBLIC/EMPS.XML")/EMPS/EMPLET$D:=DOC("/PUBLIC/DEPTS.XML") -------------------------------------------------------------------------------- <emp ename="Jack" dept="Administration"></emp><emp ename="Jill" dept="Marketing" ></emp> 1 row selected.
例5-3では、各種のFLWOR句が次の操作を行っています。
for
は/public/emps.xml
内のemp
要素について反復を実行し、変数$e
を各要素の値に順にバインドします。つまり、従業員全体のリストについて反復を実行し、$e
を各従業員にバインドします。
let
は変数$d
を、/public/emps.xml
内の、deptno
属性が要素$e
のdeptno
属性と同じであるdept
要素が持つdname
属性のすべての値で構成されているシーケンスにバインドします(結合操作)。つまり、これは$d
を、従業員$e
の部門と同じ部門番号を持つすべての部門の名前にバインドします。(depts.xml
内の各deptno
値に対してdname
値が一意であることもあり得ます)。for
と異なりlet
は値に対して反復を行わないことに注意してください。この例で、$d
は1度のみバインドされています。
for
とlet
を同時に使用すると、タプル($e
, $d
)のストリームを生成できます。ここで$e
はある従業員、$d
はその従業員が所属するすべての部門の名前(この場合は従業員の一意の部門の一意の名前)を表します。
where
はそのタプル・ストリームをフィルタリングし、給与が100,000を超える従業員のみを残します。
order by
は、フィルタリングされたタプル・ストリームを従業員番号empno
でソートします(デフォルトでは昇順)。
return
は、各タプルについて1つのemp
要素を構成します。それらの要素の属性ename
およびdept
が、それぞれ入力の属性ename
および$d
を使用して構成されます。出力内の要素名と属性名emp
およびename
と入力文書emps.xml
内の同じ名前の間に必然的な関係はないことに注意してください。
例5-4でもFLWOR式の句をそれぞれ使用しています。この例は、組込みXQuery関数 http://www.w3.org/2003/11/xpath-functions
の名前空間にあるXQuery関数doc
、count
、avg
、およびinteger
の使用方法を示しています。この名前空間は接頭辞fn
にバインドされます。
例5-4 組込み関数を使用したFLOWR式
SELECT XMLQuery('for $d in fn:doc("/public/depts.xml")/depts/dept/@deptno let $e := fn:doc("/public/emps.xml")/emps/emp[@deptno = $d] where fn:count($e) > 1 order by fn:avg($e/@salary) descending return <big-dept>{$d, <headcount>{fn:count($e)}</headcount>, <avgsal>{xs:integer(fn:avg($e/@salary))}</avgsal>} </big-dept>' RETURNING CONTENT) FROM DUAL; XMLQUERY('FOR$DINFN:DOC("/PUBLIC/DEPTS.XML")/DEPTS/DEPT/@DEPTNOLET$E:=FN:DOC("/P -------------------------------------------------------------------------------- <big-dept deptno="10"><headcount>2</headcount><avgsal>165500</avgsal></big-dept> 1 row selected.
例5-4では、各種のFLWOR句が次の操作を行っています。
for
は、入力文書/public/depts.xml
内のdeptno
属性について反復を実行し、変数$d
を各属性の値に順にバインドします。
let
は変数$e
を、入力文書/public/emps.xml
の、deptno
属性が$d
という値を持つすべてのemp
要素で構成されるシーケンスにバインドします(join操作)。
Together, for
とlet
を同時に使用すると、タプル($d
, $e
)のストリームを生成できます。ここで$d
は部門番号、$e
はその部門の従業員の集合を表します。
where
はそのタプル・ストリームをフィルタリングし、1人以上の従業員を持つタプルのみを残します。
order by
は、フィルタリングされたタプル・ストリームを平均給与の降順でソートします。平均は、名前空間fn
のXQuery関数avg
を、属性salary
の値に適用して計算します。この値は$e
のemp
要素に連結されています。
return
は、order by
で生成された各タプルについて1つのbig-dept
要素を構成します。big-dept
のtext()
ノードには、$d
にバインドされた部門番号が含まれます。XQuery関数count
で指定されたとおり、headcount
子要素には、従業員数が$e
にバインドされて含まれます。avgsal
子要素には、計算された平均給与が含まれます。
この項では、XQueryを使用してリレーショナル・データをXMLデータであるかのように問い合せる例について説明します。
例5-5では、Oracle XQuery関数fn:collection
をFLWOR式で使用して、2つのリレーショナル表regions
およびcountries
を問い合せています。どちらの表も、サンプル・データベース・スキーマHR
に属しています。この例ではさらに、SQLスカラー値Asia
がXQuery変数$regionname
に渡されています。どのSQL式でも、評価することによってPASSING
を使用してXQueryに渡す値を生成できます。その場合、値はSQL*Plus変数REGION
により与えられます。またこの値は、適切なスカラーSQLデータ型(この場合はVARCHAR2(40)
)にキャストする必要があります。
例5-5 リレーショナル表をXMLとして問い合せる
DEFINE REGION = 'Asia' SELECT XMLQuery('for $i in fn:collection("oradb:/HR/REGIONS"), $j in fn:collection("oradb:/HR/COUNTRIES") where $i/ROW/REGION_ID = $j/ROW/REGION_ID and $i/ROW/REGION_NAME = $regionname return $j' PASSING CAST('®ION' AS VARCHAR2(40)) AS "regionname" RETURNING CONTENT) AS asian_countries FROM DUAL;
これによって、次の結果が戻されます。(ここではわかりやすいように、この結果をフォーマット出力しています。)
ASIAN_COUNTRIES ----------------------------------------- <ROW> <COUNTRY_ID>AU</COUNTRY_ID> <COUNTRY_NAME>Australia</COUNTRY_NAME> <REGION_ID>3</REGION_ID> </ROW> <ROW> <COUNTRY_ID>CN</COUNTRY_ID> <COUNTRY_NAME>China</COUNTRY_NAME> <REGION_ID>3</REGION_ID> </ROW> <ROW> <COUNTRY_ID>HK</COUNTRY_ID> <COUNTRY_NAME>HongKong</COUNTRY_NAME> <REGION_ID>3</REGION_ID> </ROW> <ROW> <COUNTRY_ID>IN</COUNTRY_ID> <COUNTRY_NAME>India</COUNTRY_NAME> <REGION_ID>3</REGION_ID> </ROW> <ROW> <COUNTRY_ID>JP</COUNTRY_ID> <COUNTRY_NAME>Japan</COUNTRY_NAME> <REGION_ID>3</REGION_ID> </ROW> <ROW> <COUNTRY_ID>SG</COUNTRY_ID> <COUNTRY_NAME>Singapore</COUNTRY_NAME> <REGION_ID>3</REGION_ID> </ROW> 1 row selected.
例5-5では、各種のFLWOR句が次の操作を行っています。
for
は、fn:collection
のコールにより戻されるXML要素のシーケンスについて反復を実行します。最初のコールでは、各要素はリレーショナル表hr.regions
の行に対応し、変数$i
にバインドされます。同様に、fn:collection
の2回目のコールでは、$j
は、表hr.countries
の後続する行にバインドされます。regions
およびcountries
はXMLType
表ではないため、各表の行に対応する最上位要素はROW
です(ラッパー要素)。行要素についての反復は順序付けられていません。
where
は両方の表から行をフィルタリングし、各表でregion_id
が同一であり(region_id
に結合を実行)、region_name
がAsia
である行のペアのみを残します。
return
は、hr.countries
表からの行を、ROW
を最上位要素とする、XMLフラグメントを含むXML文書として戻します。
例5-6では、ネストされたFLWOR式でfn:collection
を使用して、リレーショナル・データを問い合せています。
例5-6 ネストされたFLWOR問合せでのリレーショナル・データの使用
CONNECT hr Enter password: password Connected. GRANT SELECT ON LOCATIONS TO OE / CONNECT oe Enter password: password Connected. SELECT XMLQuery( 'for $i in fn:collection("oradb:/OE/WAREHOUSES")/ROW return <Warehouse id="{$i/WAREHOUSE_ID}"> <Location> {for $j in fn:collection("oradb:/HR/LOCATIONS")/ROW where $j/LOCATION_ID eq $i/LOCATION_ID return ($j/STREET_ADDRESS, $j/CITY, $j/STATE_PROVINCE)} </Location> </Warehouse>' RETURNING CONTENT) FROM DUAL;
この問合せは、ネストされたFLWOR式の使用例です。アクセスするリレーショナル表は、サンプル・データベース・スキーマoe
にあるwarehouses
と、サンプル・データベース・スキーマHR
にあるlocations
です。この例をユーザーoe
として実行するには、最初にユーザーhr
として接続し、ユーザーoe
に対して、表locations
でSELECT
操作を実行する権限を付与する必要があります。
これによって、次の結果が戻されます。(ここではわかりやすいように、この結果をフォーマット出力しています。)
XMLQUERY('FOR$IINFN:COLLECTION("ORADB:/OE/WAREHOUSES")/ROWRETURN<WAREHOUSEID="{$ -------------------------------------------------------------------------------- <Warehouse id="1"> <Location> <STREET_ADDRESS>2014 Jabberwocky Rd</STREET_ADDRESS> <CITY>Southlake</CITY> <STATE_PROVINCE>Texas</STATE_PROVINCE> </Location> </Warehouse> <Warehouse id="2"> <Location> <STREET_ADDRESS>2011 Interiors Blvd</STREET_ADDRESS> <CITY>South San Francisco</CITY> <STATE_PROVINCE>California</STATE_PROVINCE> </Location> </Warehouse> <Warehouse id="3"> <Location> <STREET_ADDRESS>2007 Zagora St</STREET_ADDRESS> <CITY>South Brunswick</CITY> <STATE_PROVINCE>New Jersey</STATE_PROVINCE> </Location> </Warehouse> <Warehouse id="4"> <Location> <STREET_ADDRESS>2004 Charade Rd</STREET_ADDRESS> <CITY>Seattle</CITY> <STATE_PROVINCE>Washington</STATE_PROVINCE> </Location> </Warehouse> <Warehouse id="5"> <Location> <STREET_ADDRESS>147 Spadina Ave</STREET_ADDRESS> <CITY>Toronto</CITY> <STATE_PROVINCE>Ontario</STATE_PROVINCE> </Location> </Warehouse> <Warehouse id="6"> <Location> <STREET_ADDRESS>12-98 Victoria Street</STREET_ADDRESS> <CITY>Sydney</CITY> <STATE_PROVINCE>New South Wales</STATE_PROVINCE> </Location> </Warehouse> <Warehouse id="7"> <Location> <STREET_ADDRESS>Mariano Escobedo 9991</STREET_ADDRESS> <CITY>Mexico City</CITY> <STATE_PROVINCE>Distrito Federal,</STATE_PROVINCE> </Location> </Warehouse> <Warehouse id="8"> <Location> <STREET_ADDRESS>40-5-12 Laogianggen</STREET_ADDRESS> <CITY>Beijing</CITY> </Location> </Warehouse> <Warehouse id="9"> <Location> <STREET_ADDRESS>1298 Vileparle (E)</STREET_ADDRESS> <CITY>Bombay</CITY> <STATE_PROVINCE>Maharashtra</STATE_PROVINCE> </Location> </Warehouse> 1 row selected.
例5-6では、各種のFLWOR句が次の操作を行っています。
外側のfor
はfn:collection
により戻されたXML要素のシーケンスについて反復を実行します。各要素はリレーショナル表oe.warehouses
の行に対応していて、変数$i
にバインドされています。warehouses
はXMLType
表ではないので、行に対応する最上位の要素はROW
となります。行要素についての反復は順序付けられていません。
内側のfor
も同様にfn:collection
により戻されたXML要素のシーケンスについて反復を実行します。各要素はリレーショナル表hr.locations
の行に対応していて、変数$j
にバインドされています。
where
はタプル($i
, $j
)をフィルタリングし、location_id
の子が、$i
および$j
に対して同じであるタプルのみを残します(location_id
に基づいてjoinを実行します)。
内側のreturn
は、要素 STREET_ADDRESS
、CITY
、およびSTATE_PROVINCE
のXQueryシーケンスを、すべてlocations表のROW
要素 $j
の子、つまり、locations表の同名の列の値として構成します。
外側のreturn
は内側のreturn
の結果をLocation
要素で囲み、それをさらにWarehouse
要素で囲みます。Warehouse
要素に対して、値を表warehouses
のwarehouse_id
列から取得したid
属性を提供します。
例5-7では、SQL/XML関数XMLTable
は、XQuery問合せの結果を仮想リレーショナル・データに分解するために使用されています。この例で使用されているXQuery式は 例5-6で使用されているものと同一です。XQuery式の評価結果はWarehouse
要素のシーケンスです。関数XMLTable
は、行がWarehouse
要素である仮想リレーショナル表を生成します。正確には、仮想表の各行に対応する疑似列COLUMN_VALUE
はXMLフラグメント(XMLType
型)で、単一のWarehouse
要素を持ちます。
例5-7 XMLTableでリレーショナル表をXMLとして問い合せる
SELECT * FROM XMLTable( 'for $i in fn:collection("oradb:/OE/WAREHOUSES")/ROW return <Warehouse id="{$i/WAREHOUSE_ID}"> <Location> {for $j in fn:collection("oradb:/HR/LOCATIONS")/ROW where $j/LOCATION_ID eq $i/LOCATION_ID return ($j/STREET_ADDRESS, $j/CITY, $j/STATE_PROVINCE)} </Location> </Warehouse>');
これにより例5-6と同じ結果が生成されます。ただし、すべてのWarehouse
要素が統合され単一の行に出力されるのでなく、各Warehouse
要素が別々の行として出力される点が異なります。
COLUMN_VALUE -------------------------------------------------------- <Warehouse id="1"> <Location> <STREET_ADDRESS>2014 Jabberwocky Rd</STREET_ADDRESS> <CITY>Southlake</CITY> <STATE_PROVINCE>Texas</STATE_PROVINCE> </Location> </Warehouse> <Warehouse id="2"> <Location> <STREET_ADDRESS>2011 Interiors Blvd</STREET_ADDRESS> <CITY>South San Francisco</CITY> <STATE_PROVINCE>California</STATE_PROVINCE> </Location> </Warehouse> . . . 9 rows selected.
この項では、XQueryをXMLType
リレーショナル・データとともに使用する例を紹介します。
例5-8の問合せでは関数XMLQuery
でPASSING
句を使用して、XMLType
列warehouse_spec
をコンテキスト項目としてXQueryに渡します。これにより、領域が80,000を超えるウェアハウス(/Warehouse/ Area > 80000
)のそれぞれについてDetails
要素が作成されます。
例5-8 XMLQueryでPASSING句を使用してXMLType列を問い合せる
SELECT warehouse_name, XMLQuery( 'for $i in /Warehouse where $i/Area > 80000 return <Details> <Docks num="{$i/Docks}"/> <Rail>{if ($i/RailAccess = "Y") then "true" else "false"} </Rail> </Details>' PASSING warehouse_spec RETURNING CONTENT) big_warehouses FROM oe.warehouses;
これによって、次の出力が生成されます。
WAREHOUSE_NAME -------------- BIG_WAREHOUSES -------------- Southlake, Texas San Francisco New Jersey <Details><Docks num=""></Docks><Rail>false</Rail></Details> Seattle, Washington <Details><Docks num="3"></Docks><Rail>true</Rail></Details> Toronto Sydney Mexico City Beijing Bombay 9 rows selected.
例5-8では、関数XMLQuery
は表warehouses
の各行のwarehouse_spec
列に適用されます。各FLWOR句は次の操作を実行します。
for
は列warehouse_spec
(渡されたコンテキスト項目)の各行のWarehouse
要素について反復を実行します。各要素はそれぞれ$i
にバインドされます。反復は順序付けられていません。
where
はWarehouse
要素をフィルタリングして、Area
子の値が80,000を超えるもののみを残します。
return
はDetails
の要素のXQueryシーケンスを構成します。各要素は子要素Docks
およびRail
を含みます。構成されたDocks
要素のnum
属性はWarehouse
の子Docks
のtext()
値に設定されます。Rail
のtext()
コンテンツは、要素Warehouse
のRailAccess
属性の値に応じて、true
またはfalse
に設定されます。
例5-8のSELECT
文は、表warehouses
の各行に適用されます。XMLQuery
式は、XQuery式に一致しない行については空のシーケンスを戻します。New JerseyとSeattleの倉庫のみがXQuery問合せに適合するので、それらの倉庫についてのみ<Details>...</Details>
が戻されます。
例5-9はSQL/XML関数XMLTable
を使用して、XML Schemaに基づくデータを含むXMLType
表oe.purchaseorder
を問い合せます。PASSING
句を使用して、XMLTable
のXQuery式の引数のコンテキスト項目としてpurchaseorder
表を提供します。結果として得られる仮想表の疑似列COLUMN_VALUE
は、CostCenter
要素が値A10
を持ち、User
要素が値SMCCAIN
を持つReference
情報を含む、構成された要素A10po
を保持します。この問合せは、仮想表とデータベース表purchaseorder
の間の結合を実行します。
例5-9 XMLTABLEでXML Schemaに基づくデータを使用する
SELECT xtab.COLUMN_VALUE FROM purchaseorder, XMLTable('for $i in /PurchaseOrder where $i/CostCenter eq "A10" and $i/User eq "SMCCAIN" return <A10po pono="{$i/Reference}"/>' PASSING OBJECT_VALUE) xtab; COLUMN_VALUE --------------------------------------------------- <A10po pono="SMCCAIN-20021009123336151PDT"></A10po> <A10po pono="SMCCAIN-20021009123336341PDT"></A10po> <A10po pono="SMCCAIN-20021009123337173PDT"></A10po> <A10po pono="SMCCAIN-20021009123335681PDT"></A10po> <A10po pono="SMCCAIN-20021009123335470PDT"></A10po> <A10po pono="SMCCAIN-20021009123336972PDT"></A10po> <A10po pono="SMCCAIN-20021009123336842PDT"></A10po> <A10po pono="SMCCAIN-20021009123336512PDT"></A10po> <A10po pono="SMCCAIN-2002100912333894PDT"></A10po> <A10po pono="SMCCAIN-20021009123337403PDT"></A10po> 10 rows selected.
関数XMLTable
のPASSING
句により、XMLType
のOBJECT_VALUE
がpurchaseorder
表に渡され、XPathコンテキストとして使用されます。したがって、XMLTable
式はpurchaseorder
表に依存します。このため、表purchaseorder
は、FROM
リストのXMLTable
式よりも前に記述する必要があります。これは、データの依存関係が存在する状況では一般的な要件です。
例5-10で得られる結果は例5-9に類似しています。XMLTable
のかわりにXMLQuery
を使用してoe.purchaseorder
を問い合せます。次の2つの例では、XQuery式により戻される空のシーケンスの処理が異なります。例5-9では、これらの空のシーケンスはpurchaseorder
表を使用して結合されないため、SQL問合せの結果セットは全体で10行のみとなります。例5-10では、これらの空のシーケンスは、132行が含まれ、それぞれが表purchaseorder
の各行に対応するSQL問合せの結果セットの一部となります。10行を除いて行はすべて空で、出力でも空行となります。紙数を節約するために、ここでは空行は省略してあります。
例5-10 XMLQUERYでXML Schemaに基づくデータを使用する
SELECT XMLQuery('for $i in /PurchaseOrder
where $i/CostCenter eq "A10"
and $i/User eq "SMCCAIN"
return <A10po pono="{$i/Reference}"/>'
PASSING OBJECT_VALUE
RETURNING CONTENT)
FROM purchaseorder;
XMLQUERY('FOR$IIN/PURCHASEORDERWHERE$I/COSTCENTEREQ"A10"AND$I/USEREQ"SMCCAIN"RET
--------------------------------------------------------------------------------
<A10po pono="SMCCAIN-20021009123336151PDT"></A10po>
<A10po pono="SMCCAIN-20021009123336341PDT"></A10po>
<A10po pono="SMCCAIN-20021009123337173PDT"></A10po>
<A10po pono="SMCCAIN-20021009123335681PDT"></A10po>
<A10po pono="SMCCAIN-20021009123335470PDT"></A10po>
<A10po pono="SMCCAIN-20021009123336972PDT"></A10po>
<A10po pono="SMCCAIN-20021009123336842PDT"></A10po>
<A10po pono="SMCCAIN-20021009123336512PDT"></A10po>
<A10po pono="SMCCAIN-2002100912333894PDT"></A10po>
<A10po pono="SMCCAIN-20021009123337403PDT"></A10po>
132 rows selected.
例5-11では、XMLTable
句PASSING
およびCOLUMNS
を使用します。XQuery式は最上位のPurchaseOrder
要素について反復を実行し、コスト・センターA10
を含む発注書に対応するPO
要素を構成します。結果のPO
要素は続いてXMLTable
に渡されて処理されます。
例5-11 XMLTABLEでのPASSINGおよびCOLUMNS句の使用
SELECT xtab.poref, xtab.priority, xtab.contact FROM purchaseorder, XMLTable('for $i in /PurchaseOrder let $spl := $i/SpecialInstructions where $i/CostCenter eq "A10" return <PO> <Ref>{$i/Reference}</Ref> {if ($spl eq "Next Day Air" or $spl eq "Expedite") then <Type>Fastest</Type> else if ($spl eq "Air Mail") then <Type>Fast</Type> else ()} <Name>{$i/Requestor}</Name> </PO>' PASSING OBJECT_VALUE COLUMNS poref VARCHAR2(20) PATH 'Ref', priority VARCHAR2(8) PATH 'Type' DEFAULT 'Regular', contact VARCHAR2(20) PATH 'Name') xtab; POREF PRIORITY CONTACT -------------------- -------- -------------------- SKING-20021009123336 Fastest Steven A. King SMCCAIN-200210091233 Regular Samuel B. McCain SMCCAIN-200210091233 Fastest Samuel B. McCain JCHEN-20021009123337 Fastest John Z. Chen JCHEN-20021009123337 Regular John Z. Chen SKING-20021009123337 Regular Steven A. King SMCCAIN-200210091233 Regular Samuel B. McCain JCHEN-20021009123338 Regular John Z. Chen SMCCAIN-200210091233 Regular Samuel B. McCain SKING-20021009123335 Regular Steven X. King SMCCAIN-200210091233 Regular Samuel B. McCain SKING-20021009123336 Regular Steven A. King SMCCAIN-200210091233 Fast Samuel B. McCain SKING-20021009123336 Fastest Steven A. King SKING-20021009123336 Fastest Steven A. King SMCCAIN-200210091233 Regular Samuel B. McCain JCHEN-20021009123335 Regular John Z. Chen SKING-20021009123336 Regular Steven A. King JCHEN-20021009123336 Regular John Z. Chen SKING-20021009123336 Regular Steven A. King SMCCAIN-200210091233 Regular Samuel B. McCain SKING-20021009123337 Regular Steven A. King SKING-20021009123338 Fastest Steven A. King SMCCAIN-200210091233 Regular Samuel B. McCain JCHEN-20021009123337 Regular John Z. Chen JCHEN-20021009123337 Regular John Z. Chen JCHEN-20021009123337 Regular John Z. Chen SKING-20021009123337 Regular Steven A. King JCHEN-20021009123337 Regular John Z. Chen SKING-20021009123337 Regular Steven A. King SKING-20021009123337 Regular Steven A. King SMCCAIN-200210091233 Fast Samuel B. McCain 32 rows selected.
例5-11では、PurchaseOrder
の子から取得したデータは、PO
の子、Ref
、Type
およびName
を構成するのに使用されます。Type
のコンテンツは/PurchaseOrder/SpecialInstructions
のコンテンツから取得されますが、SpecialInstructions
のクラスはType
に対応して異なる方法で分割されます。
関数XMLTable
はXQuery評価の結果を、poref
、priority
、およびcontact
の仮想表の3つのVARCHAR2
列に分割します。DEFAULT
句は、Regular
のデフォルトのpriority
を指定するのに使用されます。
例5-12では、SQL/XML関数XMLTable
は、XMLType
コレクション要素LineItem
のXMLデータを、仮想表の個別の列に分割するために使用されています。
例5-12 XMLTABLEを使用してXMLコレクション要素をリレーショナル・データに分解する
SELECT lines.lineitem, lines.description, lines.partid, lines.unitprice, lines.quantity FROM purchaseorder, XMLTable('for $i in /PurchaseOrder/LineItems/LineItem where $i/@ItemNumber >= 8 and $i/Part/@UnitPrice > 50 and $i/Part/@Quantity > 2 return $i' PASSING OBJECT_VALUE COLUMNS lineitem NUMBER PATH '@ItemNumber', description VARCHAR2(30) PATH 'Description', partid NUMBER PATH 'Part/@Id', unitprice NUMBER PATH 'Part/@UnitPrice', quantity NUMBER PATH 'Part/@Quantity') lines; LINEITEM DESCRIPTION PARTID UNITPRICE QUANTITY -------- ------------------------------ ------------- --------- -------- 11 Orphic Trilogy 37429148327 80 3 22 Dreyer Box Set 37429158425 80 4 11 Dreyer Box Set 37429158425 80 3 16 Dreyer Box Set 37429158425 80 3 8 Dreyer Box Set 37429158425 80 3 12 Brazil 37429138526 60 3 18 Eisenstein: The Sound Years 37429149126 80 4 24 Dreyer Box Set 37429158425 80 3 14 Dreyer Box Set 37429158425 80 4 10 Brazil 37429138526 60 3 17 Eisenstein: The Sound Years 37429149126 80 3 16 Orphic Trilogy 37429148327 80 4 13 Orphic Trilogy 37429148327 80 4 10 Brazil 37429138526 60 4 12 Eisenstein: The Sound Years 37429149126 80 3 12 Dreyer Box Set 37429158425 80 4 13 Dreyer Box Set 37429158425 80 4 17 rows selected.
XQuery declare namespace
宣言をXQuery式のプロローグで使用して、名前空間の接頭辞を定義することができます。declare
default
namespace
を使用して、式のデフォルトの名前空間として名前空間を確立できます。
名前空間宣言を記述した行の末尾にセミコロン(;
)を置いた場合、SQL*Plusでは、そのセミコロンがSQLの終端文字として解釈されます。SQL*Plusを使用する場合は、この点に注意が必要です。これを避けるには、次のいずれかを実行します。
同じ行のセミコロンの後にテキストを挿入する。
同じ行のセミコロンの後に、(: :)
のようなコメントを挿入する。
SQL*PlusコマンドSET SQLTERMINATOR
を使用して、SQLの終端文字の認識を無効にする。
例5-13は、XQuery式の名前空間宣言の使用方法を示しています。
例5-13 XMLQUERYでの名前空間宣言の使用
SELECT XMLQuery('declare namespace e = "http://example.com"; ERROR: ORA-01756: quoted string not properly terminated for $i in doc("/public/empsns.xml")/e:emps/e:emp SP2-0734: unknown command beginning "for $i in ..." - rest of line ignored. ... -- This works - do not end the line with ";". SELECT XMLQuery('declare namespace e = "http://example.com"; for $i in doc("/public/empsns.xml")/e:emps/e:emp let $d := doc("/public/depts.xml")//dept[deptno=$i/@deptno]/@dname where $i/@salary > 100000 order by $i/@empno return <emp ename="{$i/@ename}" dept="{$d}"/>' RETURNING CONTENT) FROM DUAL; XMLQUERY('DECLARENAMESPACEE="HTTP://EXAMPLE.COM";FOR$IINDOC("/PUBLIC/EMPSNS.XML" -------------------------------------------------------------------------------- <emp ename="Jack" dept=""></emp><emp ename="Jill" dept=""></emp> -- This works too - add a comment after the ";". SELECT XMLQuery('declare namespace e = "http://example.com"; (: :) for $i in doc("/public/empsns.xml")/e:emps/e:emp let $d := doc("/public/depts.xml")//dept[deptno=$i/@deptno]/@dname where $i/@salary > 100000 order by $i/@empno return <emp ename="{$i/@ename}" dept="{$d}"/>' RETURNING CONTENT) FROM DUAL; XMLQUERY('DECLARENAMESPACEE="HTTP://EXAMPLE.COM";(::)FOR$IINDOC("/PUBLIC/EMPSNS. -------------------------------------------------------------------------------- <emp ename="Jack" dept=""></emp><emp ename="Jill" dept=""></emp> 1 row selected. -- This works too - tell SQL*Plus to ignore the ";". SET SQLTERMINATOR OFF SELECT XMLQuery('declare namespace e = "http://example.com"; for $i in doc("/public/empsns.xml")/e:emps/e:emp let $d := doc("/public/depts.xml")//dept[deptno=$i/@deptno]/@dname where $i/@salary > 100000 order by $i/@empno return <emp ename="{$i/@ename}" dept="{$d}"/>' RETURNING CONTENT) FROM DUAL / XMLQUERY('DECLARENAMESPACEE="HTTP://EXAMPLE.COM";FOR$IINDOC("/PUBLIC/EMPSNS.XML" -------------------------------------------------------------------------------- <emp ename="Jack" dept=""></emp><emp ename="Jill" dept=""></emp>
XQuery名前空間宣言は、XQuery式の外部では無効です。XMLTable
式で使用する名前空間接頭辞をXQuery式の外部で宣言するにはXMLNAMESPACES
句を使用します。この句はXMLTable
のXQuery式の引数でも使用できるため、XQueryプロローグを別個に宣言する必要はありません。
例5-14では、XMLNAMESPACES
は名前空間http://example.com
に対応する接頭辞e
を定義するために使用されます。このネームスペースはCOLUMNS
句とXMLTable
式のXQuery式で使用されます。
例5-14 XMLTABLEでのXMLNAMESPACES句の使用
SELECT * FROM XMLTable(XMLNAMESPACES ('http://example.com' AS "e"), 'for $i in doc("/public/empsns.xml") return $i/e:emps/e:emp' COLUMNS name VARCHAR2(6) PATH '@ename', id NUMBER PATH '@empno');
これによって、次の結果が戻されます。
NAME ID ------ ---------- John 1 Jack 2 Jill 3 3 rows selected.
修飾名e:ename
およびe:empno
がCOLUMNS
句に存在することにより、XMLNAMESPACES
句を使用する必要が生じています。そうでなければ、XQuery式のみのためにはプロローグ名前空間宣言(declare namespace e = "http://example.com"
)で十分です。
XMLTable
式で同一の名前空間が使用されているので、デフォルトの名前空間XMLNAMESPACES (DEFAULT 'http://example.com')
を使用できます。このため、修飾名$i/e:emps/e:emp
を、明示的接頭辞を使用せずに$i/emps/emp
と書いてかまいません。
XQuery式を使用するSQL問合せは、多くの場合、1つ以上の方法でリライト(最適化)できます。このような最適化は、XML問合せのリライトまたは最適化と呼ばれます。XPath式は、XQuery式の適切なサブセットです。
XPathリライトは、XML問合せリライトのサブセットであり、XPath式を使用する問合せがリライトされます。XPathリライトでは、XMLIndex
の最適化と、バイナリXMLのストリーミング評価が行われます。また、構造化記憶域やリレーショナル・データのXMLType
ビューの場合は、基礎となるオブジェクト・リレーショナル形式またはリレーショナル形式の構造へのリライトも行われます。
問合せのチューニングは、SQLのパフォーマンスと同様に、XQueryのパフォーマンスも改善することができます。XQueryのパフォーマンスをチューニングするには、該当するXML記憶域モデルと索引を選択します。
一般のデータベースの問合せと同様に、チューニングが必要かどうかは、問合せの実行計画をチェックして決定します。計画が最適でない場合は、次のマニュアルで個別のチューニング情報を参照してください。
構造化記憶域: 第8章「構造化記憶域のXPathリライト」
非構造化記憶域およびバイナリXML記憶域: 第6章「XMLTypeデータの索引付け」
また、次の式は処理コストがかかることがあり、そのため、大量のデータを処理する場合にパフォーマンスにオーバーヘッドが発生する可能性があることに注意してください。
次のOracle SQL関数を使用するSQL式(XPath式引数を受け入れる):
appendChildXML
(かわりにinsertChildXMLAfter
を使用)
insertXMLAfter
(かわりにinsertChildXMLAfter
を使用)
insertXMLBefore
(かわりにinsertChildXMLBefore
を使用)
次の軸を使用するXQuery式(かわりにforwardおよびdescendentの軸を使用):
ancestor
ancestor-or-self
descendant-or-self
following
following-sibling
namespace
parent
preceding
preceding-sibling
ノード・アイデンティティを伴うXQuery式(順序比較演算子<<
および>>
の使用など)
次の各項では、この章でここまでに示した例の一部に対する実行計画を示し、それがどのように実行されるかを説明します。
「リレーショナル・データに関するXQueryの最適化」: fn:collection
およびURIスキームoradb
を使用して、その場で作成されたXMLデータをターゲットとするXQuery式の例。
XML Schemaに基づくXMLTypeデータに対するXQueryの最適化: オブジェクト・リレーショナル形式でXML Schemaに基づくXMLType
表をターゲットとするXQuery式の例を示します。
関連項目:
|
XQuery式を使用する問合せに対しては、使用されているXMLType
記憶域モデルや索引付けなどの様々な要因によって、競合する最適化候補が複数あります。
デフォルトでは、Oracle XML DBは、優先順位付きのルール・セットに従って、特定の問合せおよびコンテキストに対して使用する最適化候補を決定します。この動作は、ルールベースのXML問合せのリライトと呼ばれます。
また、Oracle XML DBはコストベースのXML問合せのリライトを使用することもできます。このモードでは、Oracle XML DBは、特定の問合せに対する様々なXML最適化候補のパフォーマンスを評価し、最もパフォーマンスが高いと予測される組合せを選択します。
オプティマイザ・ヒント/*+ COST_XML_QUERY_REWRITE */
を使用すると、特定のSQL文に対してコストベースの最適化を強制できます。
例5-15は、XMLとしてアクセスされるリレーショナル・データに対するXMLQuery
の最適化を示します。例5-16に、同じコンテキストにおけるXMLTable
の最適化を示します。
例5-15 リレーショナル・データに関するXMLQueryの最適化
例5-6の問合せと、その実行計画をもう一度見てみます。この例は、問合せが最適化されていることを示しています。
SELECT XMLQuery( 'for $i in fn:collection("oradb:/OE/WAREHOUSES")/ROW return <Warehouse id="{$i/WAREHOUSE_ID}"> <Location> {for $j in fn:collection("oradb:/HR/LOCATIONS")/ROW where $j/LOCATION_ID eq $i/LOCATION_ID return ($j/STREET_ADDRESS, $j/CITY, $j/STATE_PROVINCE)} </Location> </Warehouse>' RETURNING CONTENT) FROM DUAL;
PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------- Plan hash value: 3341889589 ------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 2 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 41 | | | | 2 | TABLE ACCESS BY INDEX ROWID| LOCATIONS | 1 | 41 | 1 (0)| 00:00:01 | |* 3 | INDEX UNIQUE SCAN | LOC_ID_PK | 1 | | 0 (0)| 00:00:01 | | 4 | SORT AGGREGATE | | 1 | 6 | | | | 5 | TABLE ACCESS FULL | WAREHOUSES | 9 | 54 | 2 (0)| 00:00:01 | | 6 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 | ------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("LOCATION_ID"=:B1) 18 rows selected.
例5-16 リレーショナル・データに関するXMLTableの最適化
例5-7の問合せと、その実行計画をもう一度見てみます。この例は、問合せが最適化されていることを示しています。
SELECT * FROM XMLTable( 'for $i in fn:collection("oradb:/OE/WAREHOUSES")/ROW return <Warehouse id="{$i/WAREHOUSE_ID}"> <Location> {for $j in fn:collection("oradb:/HR/LOCATIONS")/ROW where $j/LOCATION_ID eq $i/LOCATION_ID return ($j/STREET_ADDRESS, $j/CITY, $j/STATE_PROVINCE)} </Location> </Warehouse>');
PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------- Plan hash value: 1021775546 ------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 9 | 54 | 2 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 41 | | | | 2 | TABLE ACCESS BY INDEX ROWID| LOCATIONS | 1 | 41 | 1 (0)| 00:00:01 | |* 3 | INDEX UNIQUE SCAN | LOC_ID_PK | 1 | | 0 (0)| 00:00:01 | | 4 | TABLE ACCESS FULL | WAREHOUSES | 9 | 54 | 2 (0)| 00:00:01 | ------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("LOCATION_ID"=:B1) 16 rows selected.
例5-17に、XML Schemaに基づくXMLType
表に関するXMLQuery
の最適化を示します。例5-18に、同じコンテキストにおけるXMLTable
の最適化を示します。
例5-17 XML Schemaに基づくXMLTypeデータを含むXMLQueryの最適化
例5-10の問合せと、その実行計画をもう一度見てみます。この例は、問合せが最適化されていることを示しています。
SELECT XMLQuery('for $i in /PurchaseOrder where $i/CostCenter eq "A10" and $i/User eq "SMCCAIN" return <A10po pono="{$i/Reference}"/>' PASSING OBJECT_VALUE RETURNING CONTENT) FROM purchaseorder;
PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------- Plan hash value: 3611789148 ------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 530 | 5 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | |* 2 | FILTER | | | | | | | 3 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 | |* 4 | TABLE ACCESS FULL| PURCHASEORDER | 1 | 530 | 5 (0)| 00:00:01 | ------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(:B1='SMCCAIN' AND :B2='A10') 4 - filter(SYS_CHECKACL("ACLOID","OWNERID",xmltype('<privilege xmlns="http://xmlns.oracle.com/xdb/acl.xsd" 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 DAV:http://xmlns.oracle.com/xdb/dav.xsd"> <read-properties/><read-contents/></privilege>'))=1) 22 rows selected.
例5-18 XML Schemaに基づくXMLTypeデータを含むXMLTableの最適化
例5-12の問合せと、その実行計画をもう一度見てみます。この例は、問合せが最適化されていることを示しています。XQueryの結果は生成されません。結果セット全体を生成するにはXMLのコレクション要素LineItem
の基礎となる記憶域の列が使用されます。
SELECT lines.lineitem, lines.description, lines.partid, lines.unitprice, lines.quantity FROM purchaseorder, XMLTable('for $i in /PurchaseOrder/LineItems/LineItem where $i/@ItemNumber >= 8 and $i/Part/@UnitPrice > 50 and $i/Part/@Quantity > 2 return $i' PASSING OBJECT_VALUE COLUMNS lineitem NUMBER PATH '@ItemNumber', description VARCHAR2(30) PATH 'Description', partid NUMBER PATH 'Part/@Id', unitprice NUMBER PATH 'Part/@UnitPrice', quantity NUMBER PATH 'Part/@Quantity') lines;
----------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 4 | 384 | 7 (0)| 00:00:01 | | 1 | NESTED LOOPS | | | | | | | 2 | NESTED LOOPS | | 4 | 384 | 7 (0)| 00:00:01 | |* 3 | TABLE ACCESS FULL | PURCHASEORDER | 1 | 37 | 5 (0)| 00:00:01 | |* 4 | INDEX RANGE SCAN | SYS_C005478 | 17 | | 1 (0)| 00:00:01 | |* 5 | TABLE ACCESS BY INDEX ROWID| LINEITEM_TABLE | 3 | 177 | 2 (0)| 00:00:01 | ----------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - filter(SYS_CHECKACL("ACLOID","OWNERID",xmltype('<privilege xmlns="http://xmlns.oracle.com/xdb/acl.xsd" 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 DAV:http://xmlns.oracle.com/xdb/dav.xsd"><read-prop erties/><read-contents/></privilege>'))=1) 4 - access("NESTED_TABLE_ID"="PURCHASEORDER"."SYS_NC0003400035$") 5 - filter("SYS_NC00013$">50 AND "SYS_NC00012$">2 AND "ITEMNUMBER">=8 AND "SYS_NC_TYPEID$" IS NOT NULL) 25 rows selected.
この例は、表oe.purchaseorder
を完全に検索します。それぞれの発注文書について、XMLTable
式が評価されます。purchaseorder
表でなくXMLTable
式にSQL問合せの実行をまかせる方が効率的です。
XQuery式はリレーショナル式にリライトされていますが、基礎となるリレーショナル・データに基づいて索引を作成することによって最適化を改善できます。この問合せは、純粋なSQL問合せを最適化する場合と同じ方法で最適化できます。これは、Oracle XML DBのXQueryには常にあてはまります。SQLで使用する最適化テクニックをそのまま使用できます。
コレクション要素LineItem
のUnitPrice
属性は、適切な索引ターゲットです。適用されるXMLスキーマが、Ordered Collection Table(OCT)を使用してLineItem
要素を格納することを指定しています。
ただし、このOCTの名前は、XML発注書がXML Schemaに基づくデータとして分解されたときに、Oracle XML DBにより生成されます。サンプル・データベース・スキーマHR
の表purchaseorder
を使用するかわりに、プロパティとデータが同じで、OCTにわかりやすい名前が付いた新しいpurchaseorder
表を(異なるデータベース・スキーマに)手動で作成します。その手順は、例3-13を参照してください。
例3-13と同様にpurchaseorder
表が作成されたと仮定すると、次の文により適切な索引が作成されます。
CREATE INDEX unitprice_index ON lineitem_table("PART"."UNITPRICE");
この索引が定義されている場合、例5-12の問合せにより、XMLTable
式が全体の評価を実行することを示す実行結果が結果として得られます。
PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------- Plan hash value: 1578014525 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 3 | 624 | 8 (0)| 00:00:01 | | 1 | NESTED LOOPS | | 3 | 624 | 8 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN| SYS_IOT_TOP_49323 | 3 | 564 | 5 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN| UNITPRICE_INDEX | 20 | | 2 (0)| 00:00:01 | |* 4 | INDEX UNIQUE SCAN| SYS_C004411 | 1 | | 0 (0)| 00:00:01 | ---------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("SYS_NC00013$">50) filter("ITEMNUMBER">=8 AND "SYS_NC00012$">2) 3 - access("SYS_NC00013$">50) 4 - access("NESTED_TABLE_ID"="PURCHASEORDER"."SYS_NC0003400035$") Note ----- - dynamic sampling used for this statement 23 rows selected.
SQLコードの実行計画を調べて、XQueryの最適化が行われるか、計画が部分的に最適化されるかを判断できます。後者の場合は、計画の直後に次のような注記が表示されます。
Unoptimized XML construct detected (enable XMLOptimizationCheck for more information)
また、実行計画の出力をオプティマイザ・ヒントNO_XML_QUERY_REWRITE
の後に表示される計画の出力と比較することもできます。これによってXQueryの最適化がオフになります。
さらに、SQL*PlusのSET
コマンドでシステム変数XMLOptimizationCheck
を使用して、SQLのXML診断能力モードをオンにすることができます。
SET XMLOptimizationCheck ON
このモードがオンの場合、XQuery最適化の実行計画が自動的にチェックされ、計画が部分的な最適化の場合は、エラーが発生して診断情報がトレース・ファイルに書き込まれ、どの演算子が書きなおされていないのかが示されます。
XMLOptimizationCheck
の主な利点は、潜在的な問題がただちに明らかになることです。このため、常にこのモードをオンにしておくのが望ましいと言えます。そして、何らかの理由でアプリケーションやデータベースに変更が生じたため、SQL操作で書き直しができない場合、原因に気がつかないうちにパフォーマンスが低下するかわりに実行が停止します。
注意:
|
Oracle XML DBでは、XQuery関数fn:doc
およびfn:collection
を使用して、Oracle XML DBリポジトリ内の文書やコレクションを参照できます。リポジトリのXMLTypeデータがオブジェクト・リレーショナル形式またはバイナリXML形式で格納されている場合、fn:doc
およびfn:collection
を使用する問合せは関数として評価されます。つまり、これらは基礎となる記憶域表に直接アクセスできるように最適化されていません。
こうした問合せのパフォーマンスを向上するには、問い合せるリポジトリ・データを保持する実際のデータベースの表にそれらをリンクする必要があります。これを行うには、次のいずれかの方法を実行します。
RESOURCE_VIEW
ビューを、データを保持するXMLType
表と結合し、XQuery関数fn:doc
およびfn:collection
のかわりに、Oracle SQL関数equals_path
およびunder_path
をそれぞれ使用します。これらのSQL関数は、パフォーマンスに優れた方法でリポジトリ・リソースを参照します。
Oracle XQuery拡張式プラグマora:defaultTable
を使用します。
どちらの方法を使用しても結果は同じです。XQueryの標準関数fn:doc
とfn:collection
を引き続き使用できるほか、コードが簡略化されるため、ora:defaultTable
プラグマの使用をお薦めします。
この項の例で、これらの2つの方法について説明しています。
SQL関数equals_path
およびunder_path
は、それぞれ指定したリポジトリ・パスにあるリソースを参照します。例5-19および例5-20に、関数fn:doc
およびequals_path
でのこの処理を示します。関数fn:collection
およびunder_path
が同じように処理されます。
例5-19 fn:docを使用した、最適化されていないリポジトリの問合せ
SELECT XMLQuery('let $val := fn:doc("/home/OE/PurchaseOrders/2002/Sep/VJONES-20021009123337583PDT.xml") /PurchaseOrder/LineItems/LineItem[@ItemNumber =19] return $val' RETURNING CONTENT) FROM DUAL;
例5-20 EQUALS_PATHを使用した、最適化されたリポジトリの問合せ
SELECT XMLQuery('let $val := $DOC/PurchaseOrder/LineItems/LineItem[@ItemNumber = 19] return $val' PASSING OBJECT_VALUE AS "DOC" RETURNING CONTENT) FROM RESOURCE_VIEW rv, purchaseorder p WHERE ref(p) = XMLCast(XMLQuery('declare default element namespace "http://xmlns.oracle.com/xdb/XDBResource.xsd"; (: :) fn:dataFoot 6 (/Resource/XMLRef)' PASSING rv.RES RETURNING CONTENT) AS REF XMLType) AND equals_path(rv.RES, '/home/OE/PurchaseOrders/2002/Sep/VJONES-20021009123337583PDT.xml') = 1;
Oracle XQuery拡張式プラグマora:defaultTable
を使用すると、問い合せるリポジトリ・データを格納するデフォルトの表を指定できます。問合せは、デフォルトのテーブルをRESOURCE_VIEW
ビューに自動的に結合し、XQuery関数fn:doc
とfn:collection
のかわりに、Oracle SQL関数equals_path
およびunder_path
を使用するようにリライトされます。このため結果は、手動で問合せのコードを記述して、明示的な結合およびequals_path
やunder_path
を使用する場合と同じです。例5-21に、この詳細を説明します。問合せが自動的にリライトされ、例5-20のようになります。
例5-21 Oracle XQueryプラグマora:defaultTableを使用したリポジトリの問合せ
SELECT XMLQuery('for $doc in (#ora:defaultTable PURCHASEORDER #)
{fn:doc("/home/OE/PurchaseOrders/2002/Sep/VJONES-20021009123337583PDT.xml")}
let $val := $doc/PurchaseOrder/LineItems/LineItem[@ItemNumber = 19]
return $val}'
RETURNING CONTENT)
FROM DUAL;
範囲を明確にするため、プラグマora:defaultTable
を、大きい式ではなく適切な文書やコレクションの式、fn:doc
またはfn:collection
に直接適用することをお薦めします。
Oracle XML DBはすべてのXQuery式を型チェックします。しかし、実行時の型チェックはコストがかかることがあります。最適化技法として、指定された問合せに対してコンパイル時に十分な静的型情報を利用できる場合は常に、Oracle XML DBはその問合せの静的な(コンパイル時)型チェックを行います。指定された問合せに対してコンパイル時に十分な静的型情報を利用できない場合は、Oracle XML DBはその問合せの動的(実行時)型チェックを使用します。
静的型チェックでは、コンパイル時にエラーが発生するので、実行時間を節約できることがあります。静的型チェック・エラーには、データ型エラーと、XML Schemaの観点から無効であるXPath式の使用の両方を含みます。
コンパイル時に十分な静的型情報を提供する一般的な方法には、次の方法があります。
リレーショナル・データに関してXQueryとfn:doc
またはfn:collection
を使用。
XQueryを使用して、問合せコンパイル時にXML Schema情報を利用できるXMLType
表、列またはビューを問い合せます。
この項では、静的型チェックの有効性と、型情報を通信するこれら2つの手段の使用方法を示す例を紹介します。
fn:collection
およびURIスキームoradb
によってその場で生成されるXMLデータは、ROW
を最上位の要素に持ちますが、例5-22の問合せには、ROW
のラッパー要素が欠けています。この脱落により、問合せのコンパイル時エラーが発生します。このようにfn:collection
とoradb
によりリレーショナル・データをラップし忘れる誤りはよくあることですが、静的型チェックがないと、診断が困難な場合があります。例5-5に正しいコードを示します。
例5-22 XQuery式の静的型チェック: oradb URIスキーム
-- This produces a static-type-check error, because "ROW" is missing. SELECT XMLQuery('for $i in fn:collection("oradb:/HR/REGIONS"), $j in fn:collection("oradb:/HR/COUNTRIES") where $i/REGION_ID = $j/REGION_ID and $i/REGION_NAME = "Asia" return $j' RETURNING CONTENT) AS asian_countries FROM DUAL; SELECT XMLQuery('for $i in fn:collection("oradb:/HR/REGIONS"), * ERROR at line 1: ORA-19276: XPST0005 - XPath step specifies an invalid element/attribute name: (REGION_ID)
例5-23では、XQueryの静的型チェックにより、XPath式とそのターゲットXML Schemaに基づくデータの不一致を検出します。要素CostCenter
が、ここではcostcenter
と誤ったスペルになっています(XQueryおよびXPathは大文字/小文字を区別します)。例5-11に正しいコードを示します。
例5-23 XQuery式の静的型チェック: スキーマベースのXML
-- This results in a static-type-check error: CostCenter is not the right case.
SELECT xtab.poref, xtab.usr, xtab.requestor
FROM purchaseorder,
XMLTable('for $i in /PurchaseOrder where $i/costcenter eq "A10" return $i'
PASSING OBJECT_VALUE
COLUMNS poref VARCHAR2(20) PATH 'Reference',
usr VARCHAR2(20) PATH 'User' DEFAULT 'Unknown',
requestor VARCHAR2(20) PATH 'Requestor') xtab;
FROM purchaseorder,
*
ERROR at line 2:
ORA-19276: XPST0005 - XPath step specifies an invalid element/attribute name:
(costcenter)
例5-24は、XQuery式の前にSQL*PlusコマンドXQUERY
を付け、式の後にスラッシュ(/
)を単独で付けることにより、SQL*PlusコマンドラインでXQuery式を直接入力する方法を示します。Oracle Databaseでは、このコマンドで送信されたXQuery式を、SQL/XML関数XMLQuery
およびXMLTable
内のXQuery式と同様に処理します。実行は同一で、同じ最適化を使用します。
例5-24 SQL*Plus XQUERYコマンドの使用
SQL> XQUERY for $i in fn:collection("oradb:/HR/DEPARTMENTS") 2 where $i/ROW/DEPARTMENT_ID < 50 3 return $i 4 / Result Sequence -------------------------------------------------------------------------------- <ROW><DEPARTMENT_ID>10</DEPARTMENT_ID><DEPARTMENT_NAME>Administration</DEPARTMEN T_NAME><MANAGER_ID>200</MANAGER_ID><LOCATION_ID>1700</LOCATION_ID></ROW> <ROW><DEPARTMENT_ID>20</DEPARTMENT_ID><DEPARTMENT_NAME>Marketing</DEPARTMENT_NAM E><MANAGER_ID>201</MANAGER_ID><LOCATION_ID>1800</LOCATION_ID></ROW> <ROW><DEPARTMENT_ID>30</DEPARTMENT_ID><DEPARTMENT_NAME>Purchasing</DEPARTMENT_NA ME><MANAGER_ID>114</MANAGER_ID><LOCATION_ID>1700</LOCATION_ID></ROW> <ROW><DEPARTMENT_ID>40</DEPARTMENT_ID><DEPARTMENT_NAME>Human Resources</DEPARTME NT_NAME><MANAGER_ID>203</MANAGER_ID><LOCATION_ID>2400</LOCATION_ID></ROW>
XQueryに固有の設定で使用できるSQL*Plus SET
コマンドもいくつかあります。現在の設定を参照するにはSHOW XQUERY
を使用します。
SET XQUERY BASEURI
: XQUERY
のベースURIを設定します。XQuery式内のURIは、このURIに相対的です。
SET XQUERY CONTEXT
: 以降のXQUERY
評価で使用するコンテキスト項目を指定します。
関連項目: 『SQL*Plusユーザーズ・ガイドおよびリファレンス』 |
この章の前項で、SQLからXQueryを呼び出す方法を示しました。この項では、XQueryを、PL/SQL、JDBC、およびOracle Data Provider for .NET(ODP.NET)用のOracle APIとともに使用する例を示します。
例5-25は、XQueryをPL/SQLとともに使用する方法、特に、XMLQuery
のPASSING
句を使用して動的変数をXQuery式にバインドする方法を示します。バインド変数:1
および:2
は、PL/SQLバインド変数nbitems
およびpartid
に、それぞれバインドされます。その後、それぞれXQuery変数itemno
およびid
としてXQueryに渡されます。
例5-25 XQueryをPL/SQLとともに使用する
DECLARE sql_stmt VARCHAR2(2000); -- Dynamic SQL statement to execute nbitems NUMBER := 3; -- Number of items partid VARCHAR2(20):= '715515009058'; -- Part ID result XMLType; doc DBMS_XMLDOM.DOMDocument; ndoc DBMS_XMLDOM.DOMNode; buf VARCHAR2(20000); BEGIN sql_stmt := 'SELECT XMLQuery( ''for $i in fn:collection("oradb:/OE/PURCHASEORDER") ' || 'where count($i/PurchaseOrder/LineItems/LineItem) = $itemno ' || 'and $i/PurchaseOrder/LineItems/LineItem/Part/@Id = $id ' || 'return $i/PurchaseOrder/LineItems'' ' || 'PASSING :1 AS "itemno", :2 AS "id" ' || 'RETURNING CONTENT) FROM DUAL'; EXECUTE IMMEDIATE sql_stmt INTO result USING nbitems, partid; doc := DBMS_XMLDOM.newDOMDocument(result); ndoc := DBMS_XMLDOM.makeNode(doc); DBMS_XMLDOM.writeToBuffer(ndoc, buf); DBMS_OUTPUT.put_line(buf); END; /
これによって、次の出力が生成されます。
<LineItems> <LineItem ItemNumber="1"> <Description>Samurai 2: Duel at Ichijoji Temple</Description> <Part Id="37429125526" UnitPrice="29.95" Quantity="3"/> </LineItem> <LineItem ItemNumber="2"> <Description>The Red Shoes</Description> <Part Id="37429128220" UnitPrice="39.95" Quantity="4"/> </LineItem> <LineItem ItemNumber="3"> <Description>A Night to Remember</Description> <Part Id="715515009058" UnitPrice="39.95" Quantity="1"/> </LineItem> </LineItems> <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> PL/SQL procedure successfully completed.
例5-26は、XQueryをJDBCとともに使用して、変数をその位置によってSQL/XML関数XMLTable
のPASSING
句にバインドします。
例5-26 XQueryをJDBCとともに使用する
import java.sql.*; import oracle.sql.*; import oracle.jdbc.*; import oracle.xdb.XMLType; import java.util.*; public class QueryBindByPos { public static void main(String[] args) throws Exception, SQLException { System.out.println("*** JDBC Access of XQuery using Bind Variables ***"); DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); OracleConnection conn = (OracleConnection) DriverManager.getConnection("jdbc:oracle:oci8:@localhost:1521:ora11gR1", "oe", "oe"); String xqString = "SELECT COLUMN_VALUE" + "FROM XMLTable('for $i in fn:collection(\"oradb:/OE/PURCHASEORDER\") " + "where $i/PurchaseOrder/Reference= $ref " + "return $i/PurchaseOrder/LineItems' " + "PASSING ? AS \"ref\")"; OraclePreparedStatement stmt = (OraclePreparedStatement)conn.prepareStatement(xqString); String refString = "EABEL-20021009123336251PDT"; // Set the filter value stmt.setString(1, refString); // Bind the string ResultSet rs = stmt.executeQuery(); while (rs.next()) { XMLType desc = (XMLType) rs.getObject(1); System.out.println("LineItem Description: " + desc.getStringVal()); desc.close(); } rs.close(); stmt.close(); } }
これによって、次の出力が生成されます。
*** JDBC Access of Database XQuery with Bind Variables *** LineItem Description: Samurai 2: Duel at Ichijoji Temple LineItem Description: The Red Shoes LineItem Description: A Night to Remember
例5-27は、XQueryをODP.NETおよびC#言語とともに使用する方法を示します。C#の入力パラメータ:nbitems
および:partid
は、それぞれXQuery変数itemno
およびid
としてXQueryに渡されます。
例5-27 XQueryをODP.NETおよびC#とともに使用する
using System; using System.Data; using System.Text; using System.IO; using System.Xml; using Oracle.DataAccess.Client; using Oracle.DataAccess.Types; namespace XQuery { /// <summary> /// Demonstrates how to bind variables for XQuery calls /// </summary> class XQuery { /// <summary> /// The main entry point for the application. /// </summary> static void Main(string[] args) { int rows = 0; StreamReader sr = null; // Create the connection. string constr = "User Id=oe;Password=***********;Data Source=ora11gr2"; // Replace with real password. OracleConnection con = new OracleConnection(constr); con.Open(); // Create the command. OracleCommand cmd = new OracleCommand("", con); // Set the XML command type to query. cmd.CommandType = CommandType.Text; // Create the SQL query with the XQuery expression. StringBuilder blr = new StringBuilder(); blr.Append("SELECT COLUMN_VALUE FROM XMLTable"); blr.Append("(\'for $i in fn:collection(\"oradb:/OE/PURCHASEORDER\") "); blr.Append(" where count($i/PurchaseOrder/LineItems/LineItem) = $itemno "); blr.Append(" and $i/PurchaseOrder/LineItems/LineItem/Part/@Id = $id "); blr.Append(" return $i/PurchaseOrder/LineItems\' "); blr.Append(" PASSING :nbitems AS \"itemno\", :partid AS \"id\")"); cmd.CommandText = blr.ToString(); cmd.Parameters.Add(":nbitems", OracleDbType.Int16, 3, ParameterDirection.Input); cmd.Parameters.Add(":partid", OracleDbType.Varchar2, "715515009058", ParameterDirection.Input); // Get the XML document as an XmlReader. OracleDataReader dr = cmd.ExecuteReader(); dr.Read(); // Get the XMLType column as an OracleXmlType OracleXmlType xml = dr.GetOracleXmlType(0); // Print the XML data in the OracleXmlType object Console.WriteLine(xml.Value); xml.Dispose(); // Clean up. cmd.Dispose(); con.Close(); con.Dispose(); } } }
これによって、次の出力が生成されます。
<LineItems> <LineItem ItemNumber="1"> <Description>Samurai 2: Duel at Ichijoji Temple</Description> <Part Id="37429125526" UnitPrice="29.95" Quantity="3"/> </LineItem> <LineItem ItemNumber="2"> <Description>The Red Shoes</Description> <Part Id="37429128220" UnitPrice="39.95" Quantity="4"/> </LineItem> <LineItem ItemNumber="3"> <Description>A Night to Remember</Description> <Part Id="715515009058" UnitPrice="39.95" Quantity="1"/> </LineItem> </LineItems>
この項では、XQuery言語のためのOracle XML DBについて説明します。
Oracle XML DBのXQuery言語サポートは、リレーショナル記憶域の使用範囲とXMLデータの問合せの使用範囲のベスト・フィットの実現を目指しています。つまり、Oracle XML DBは一般的なXQuery実装ですが、それと同時に、リレーショナル問合せとXML問合せの連携動作に特に注意して設計されています。
この項では、Oracle XML DBのXQuery実装の個別のプロパティについて説明します。XQuery標準は、言語処理の一部の特性について、実装により定義されるのか、実装に依存するのかを明示的にコール・アウトしています。また、XQuery標準で規定されているが、Oracle XML DBでサポートされていない機能もいくつかあります。
XQuery仕様では、言語処理の次の点に関しては実装により定義するように指定されています。
暗黙的タイムゾーン・サポート: Oracle XML DBでは、暗黙的タイムゾーンを常にZ
と仮定しています。タイムゾーンのないxs:date
、xs:time
およびxs:datetime
のインスタンスは、自動的にUTCに変換されます。
XQuery標準で規定されている次の機能は、Oracle XML DBではサポートされていません。
copy-namespacesモード: Oracle XML DBでcopy-namespaces
宣言についてサポートされるのは、preserve
とinherit
のみです。既存の要素ノードが要素コンストラクタまたは文書コンストラクタによりコピーされた場合、元の要素の範囲にあるすべてのネームスペースはコピー内に保持されます。そうでない場合は、コピーされたノードは構築されたノードの範囲内にあるすべてのネームスペースを継承します。no-preserve
またはno-inherit
を指定するとエラーが発生します。
バージョン・エンコーディング: Oracle XML DBでは、バージョン宣言の中のオプションのエンコーディング宣言はサポートされません。つまり、(encoding
an-encoding
)
を宣言xquery version
a-version
;
の中に含むことはできません。特に、問合せで使用するエンコーディングは指定できません。エンコーディング宣言が含まれるとエラーが発生します。
xml:id: Oracle XML DBでは、xml:id
の使用はサポートされません。xml:id
を使用するとエラーが発生します。
XQueryプロローグのデフォルト照合宣言
XQueryプロローグの境界空間宣言
XQueryデータ型xs:duration
。かわりにxs:yearMonthDuration
またはxs:DayTimeDuration
を使用します。
XQuery標準で規定されている次のオプション機能は、Oracle XML DBではサポートされていません。
スキーマ検証機能
モジュール機能
Oracle XML DBでは、XQuery 1.0およびXPath 2.0の関数および演算子の最新の仕様に含まれるXQueryの関数と演算子がすべてサポートされていますが、次の例外があります。次のものはサポートされていません。
XQueryの正規表現関数(fn:matches
、fn:replace
およびfn:tokenize
)。これらのかわりに、Oracle XQuery関数ora:matches
、ora:replace
およびora:tokenize
をそれぞれ使用してください。
関数fn:id
およびfn:idref
。
引数のない関数fn:collection
。
XQuery関数のオプションの照合パラメータ。
Oracle XML DBでは、Oracle XML DBリポジトリにあるすべてのリソースについて、XQuery関数fn:doc
、fn:collection
およびfn:doc-available
がサポートされています。
関数fn:doc
はURI引数によりターゲットとされているリポジトリのファイル・リソースを戻します。このリソースは整形式のXMLデータのファイルにしてください。関数fn:collection
も同様ですが、リポジトリのフォルダ・リソースに対して機能します(フォルダ内の各ファイルには整形式のXMLデータが含まれている必要があります)。
Oracle URIスキームoradb
とともに使用すると、fn:collection
は既存のリレーショナル・データからその場で派生した、リポジトリにないXMLデータを戻すことができます。
XQuery関数fn:collection
は、URIスキームoradb
とともに使用した場合、ターゲットの表やビュー、列が存在しないと、エラーが発生します。関数fn:doc
とfn:collection
では、引数として引き渡されたリポジトリのリソースが見つからない場合、エラーは発生しません。かわりに、空のシーケンスが戻されます。
任意の文書が存在するかどうかは、XQuery関数fn:doc-available
を使用して判断できます。文書の引数が存在する場合はtrue
、存在しなければfalse
がそれぞれ戻されます。
脚注の凡例
脚注1: 戻り値は、通常と同様、シーケンスです。ただしXQueryでは、項目が1つのシーケンスはその項目自身と等価です。この場合、その単独の項目はブール値です。xs
は、XML Schemaの名前空間http://www.w3.org/2001/XMLSchema
であらかじめ定義されています。?
)は0回または1回出現することを示すインジケータで、引数が空のシーケンスである場合もあります。「XQuery式」を参照してください。?
)は0回または1回出現することを示すインジケータで、引数が空のシーケンスである場合もあります。「XQuery式」を参照してください。?
)は0回または1回出現することを示すインジケータで、引数が空のシーケンスである場合もあります。「XQuery式」を参照してください。fn:data
は、その引数の分解に使用されます。この場合は、XMLRef
ノード型指定されたアトミック値を戻します。