この章では、Oracle XML DBでのXPathリライトの基礎、およびそれをXML Schemaに基づく構造化記憶域に対して使用する方法について説明します。SQL関数(existsNode
、extract
、extractValue
、XMLSequence
、updateXML
、insertChildXMl
およびdeleteXML
)のXPath式引数のリライトについて詳しく説明します。
この章の内容は次のとおりです。
オブジェクト・リレーショナル形式(構造化記憶域)で格納されているXML Schemaに基づくデータでは、XQuery式を使用してそのデータを問い合せると、多くの場合、問合せは基礎となるオブジェクト・リレーショナル列に直接リライトされます。このクエリー・リライトは、特定のXML Schemaに基づかないXMLType
ビューでXQuery式を使用して問合せを行った場合も発生します。XQuery式のリライトの最適化プロセスを、XPathリライトといいます。
この最適化によって、Bツリーまたは他の索引が列に存在する場合、これらをオプティマイザによる問合せの評価に使用できます。XPathリライトのメカニズムは、XMLQuery
、XMLTable
、XMLExists
、existsNode
、extract
、extractValue
、updateXML
などのSQL関数へのXPath式引数に対して使用されます。これにより、メモリー内でXML文書を構成せずに、XPath式をXML文書に対して評価できます。
Oracle XML DBによってリライトされるXPath式は、Oracle XML DBでサポートされるXPath式の適切なサブセットです。機能性を損なわずにXPath式をリライトできる場合は、リライト可能なXPath式を使用してください。
例7-1 XPathリライト
たとえば、次のような問合せでは、Company
要素の値の取得およびリテラル文字列Oracle
との比較が試行されます。
SELECT OBJECT_VALUE FROM mypurchaseorders WHERE extractValue(OBJECT_VALUE, '/PurchaseOrder/Company') = 'Oracle';
表mypurchaseorders
がXML Schemaに基づく構造化記憶域で作成されているとすると、extractValue
式は、発注書についての企業情報を格納する基礎となるリレーショナル列にリライトされます。問合せは次のようにリライトされます。
SELECT VALUE(p) FROM mypurchaseorders p WHERE p.XMLDATA."Company" = 'Oracle';
Company
列に対して次のような索引が作成されている場合、前述の問合せでは、問合せの評価にこの索引が使用されます。
CREATE INDEX company_index ON mypurchaseorders e (extractValue(OBJECT_VALUE, '/PurchaseOrder/Company'));
XPathリライトは、XML Schemaに基づく表、およびXML Schemaに基づくビューとXML Schemaに基づかないビューに対して発生します。この章では、XML Schemaに基づく表に関する例のみを考えます。
例7-2のSQL関数updateXML
のXPath引数は、同等のオブジェクト・リレーショナルなSQL文例7-3にリライトされます。
例7-2 UPDATEXMLでのXPathリライト
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/User')
FROM purchaseorder
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;
EXTRACTVAL
----------
SBELL
1 row selected.
UPDATE purchaseorder
SET OBJECT_VALUE = updateXML(OBJECT_VALUE, '/PurchaseOrder/User/text()', 'SVOLLMAN')
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;
1 row updated.
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/User')
FROM purchaseorder
WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;
EXTRACTVAL
----------
SVOLLMAN
1 row selected.
例7-3 UPDATEXMLでのXPathリライトによるリライト済オブジェクト・リレーショナル文
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/User') FROM purchaseorder WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1; EXTRACTVAL ---------- SBELL 1 row selected. UPDATE purchaseorder p SET p."XMLDATA"."userid" = 'SVOLLMAN' WHERE p."XMLDATA"."reference" = 'SBELL-2002100912333601PDT'; 1 row updated. SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/User') FROM purchaseorder WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1; EXTRACTVAL ---------- SVOLLMAN 1 row selected.
関連項目: XML Schemaに基づくビューおよびXML Schemaに基づかないビューに対する他のXPathリライト例は、第3章「Oracle XML DBの使用」の「XPathリライトの理解および最適化」を参照してください。 |
XPathリライトは、次のSQL関数に対して行われます。
deleteXML
existsNode
extract
extractValue
insertChildXML
updateXML
XMLExists
XMLQuery
XMLSequence
XMLTable
XPathリライトは、問合せ、DML文またはDDL文のいずれかの式にこれらのSQL関数が存在している場合に行われます。たとえば、関数extractValue
を使用して、基礎となるリレーショナル列に対する索引を作成できます。
例7-4 SELECT文とXPathリライト
この例では、既存の発注書を戻します。
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Company') FROM mypurchaseorders x WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder/Item[1]/Part') = 1;
例7-5および例7-6に、基礎となる列を使用するようにリライトされる文をいくつか示します。例7-5は、Company
がOracle
でないすべてのPurchaseOrder
要素を削除します。
例7-5 DML文とXPathリライト
DELETE FROM mypurchaseorders x WHERE extractValue(OBJECT_VALUE, '/PurchaseOrder/Company') = 'Oracle Corp';
例7-6はCompany
列に索引を作成します。
例7-6 CREATE INDEX文とXPathリライト
CREATE INDEX company_index ON mypurchaseorders e (extractValue(OBJECT_VALUE,'/PurchaseOrder/Company'));
Company
列はオブジェクト・リレーショナル形式で格納されているため、XPathリライトが行われると、基礎となるリレーショナル列に対して索引が作成されます。この場合、SQL関数のリライトによって単純なリレーショナル列が生成されると、索引は、ファンクション索引ではなくBツリーまたは列に対するドメイン索引に変換されます。
通常、次のすべての条件が満たされている場合に、XPath式はリライト可能です。
SQL関数またはXMLType
メソッドがリライト可能な場合。
SQL関数XMLQuery
、XMLTable
、XMLExists
、extract
、existsNode
、extractValue
、updateXML
、insertChildXML
、deleteXML
およびXMLSequence
がリライトされます。メソッドexistsNode()
およびextract()
を除き、対応するXMLType
メソッドはいずれもリライトできません。
XPath式がdescendant
軸のみを使用している場合。
descendant
以外の軸(parent軸
やsibling軸など)が含まれている式は、リライトできません。属性、要素またはテキストのノードを選択する式は、リライト可能です。XPath述語は、SQL述語にリライトできます。
XPath式のXML Schema構造体がリライト可能な場合。
複合型、列挙値、リスト、継承(導出)された型、代替グループなどのXML Schema構造体がリライトできます。
XML Schemaの登録時に選択された記憶域構造がリライト可能な場合。
オブジェクト・リレーショナル形式(構造化記憶域)で格納されたXMLデータはリライトできます。CLOB
インスタンス(ハイブリッド記憶域)を使用する複合型の記憶域はリライトできません。
表7-1に、基礎となるSQL問合せに変換できるXPath式の一部の種類を示します。
表7-1 基礎となるSQL構造体にリライトされるXPath式のサンプル・リスト
変換されるXPath式 | 説明 |
---|---|
単純なXPath式:
|
属性自体が単純なスカラー型またはオブジェクト型である場合、オブジェクト型の属性のみに対して全検索が行われます。サポートされる軸は、child軸およびattribute軸のみです。 |
コレクション全検索式:
|
コレクション式の全検索が行われます。サポートされる軸は、child軸およびattribute軸のみです。 |
述語:
|
XPathの述語は、SQL述語にリライトされます。 |
リスト索引(位置指定述語):
|
コレクションのn番目の項目にアクセスするように索引がリライトされます。 |
ワイルド・カード全検索:
|
ワイルド・カードを一意のXPathに変換できる場合(たとえば、 |
descendant軸(XML Schemaに基づくデータのみ):
|
ワイルド・カード式と同様です。descendent軸が一意のXPath式にマップされ、後続する要素が再帰型の定義に含まれていない場合は、descendent軸がリライトされます。ただし、再帰型の定義が存在しても、リライトできる場合があります。 |
Oracleで提供する拡張関数およびいくつかのXPath関数
|
Oracle XML DBの名前空間( |
述語内の文字列バインド変数
|
連結演算子( |
|
|
脚注1 table
とXMLSequence
を使用するかわりに、よりわかりやすい標準のSQL/XML関数XMLTable
を使用することもできます。
complexType
要素やシーケンスなどの標準的なXML Schema構造体に加え、次のXML Schema構造体もサポートされます。これは完全なリストではありません。
述語にスカラー値が使用されているスカラー値のコレクション。
属性を含んでいる単純型の拡張。
列挙単純型。
ブール単純型。
複合型の継承。
代用グループ。
次のXML Schema構造体はサポートされません。XPath式に次のXML Schema構造体を持つノードが含まれている場合、式はリライトされません。
any
コンテンツを含む要素の子にアクセスするXPath式。ノードにany
コンテンツが含まれる場合、XPathに指定された名前空間以外の名前空間をany
がターゲットとする場合を除き、式はリライトされません。any
属性も同様の方法で処理されます。
ブール値と数値の合計など、強制変換できないデータ型の操作。
リライトされたXPath問合せと機能的に評価されたXPath問合せは、ほとんど差異がありません。ただし、XPathのリライトはXML Schema情報を使用してXPath述語をSQL述語に変換するため、数値以外のエンティティの比較には差異があります。
XPath 1.0で、比較演算子>
、<
、>=
および<=
は、数値の比較のみに使用します。2つのオペランドは、比較の前に数値に変換されます。数値への変換のいずれかが失敗した場合、比較の結果としてfalse
が戻ります。
たとえば、XML Schemaに基づく次のような要素定義の場合、[ShipDate < '2003-02-01']
などのXPath述語は常に、機能上の評価でfalse
に評価されます。
<element name="ShipDate" type="xs:date" xdb:SQLType="DATE"/>
これは、文字列'2003-02-01'
を数量に変換できないためです。一方、XPathリライトでは、この述語はSQLの日付比較に変換され、ShipDate
の値に従ってtrue
またはfalse
に評価されます。
同様に、別のコレクション値と比較するコレクション値がある場合、XPath 1.0のセマンティクスでは、値を文字列に変換してから比較する必要があります。ただしXPathリライトでは、SQLの値を比較するためのルールを使用して比較が行われます。
比較動作の違いを抑制する場合は、問合せのヒントまたはセッション・レベルのイベントを使用してリライトを無効にできます。
この項では、この章で前出の発注書XML Schemaを使用します。
例7-7 XML Schemaに基づく発注データの作成
DECLARE doc VARCHAR2(2000) := '<schema targetNamespace="http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd" xmlns:po="http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <complexType name="PurchaseOrderType"> <sequence> <element name="PONum" type="decimal"/> <element name="Company"> <simpleType> <restriction base="string"> <maxLength value="100"/> </restriction> </simpleType> </element> <element name="Item" maxOccurs="1000"> <complexType> <sequence> <element name="Part"> <simpleType> <restriction base="string"> <maxLength value="20"/> </restriction> </simpleType> </element> <element name="Price" type="float"/> </sequence> </complexType> </element> </sequence> </complexType> <element name="PurchaseOrder" type="po:PurchaseOrderType"/> </schema>'; BEGIN DBMS_XMLSCHEMA.registerSchema( 'http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd', doc); END; /
XML Schema登録では、内部的なSQLデータ型が作成されます。これによって、XML値を格納する表およびItemを格納するOrdered Collection Tableを作成できるようになりました。
CREATE TABLE mypurchaseorders OF XMLType XMLSchema "http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd" ELEMENT "PurchaseOrder" VARRAY XMLDATA."Item" STORE AS TABLE item_nested; Table created
次に、発注書をこの表に挿入します。
INSERT INTO mypurchaseorders VALUES( XMLType( '<PurchaseOrder xmlns="http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd"> <PONum>1001</PONum> <Company>Oracle Corp</Company> <Item> <Part>9i Doc Set</Part> <Price>2550</Price> </Item> <Item> <Part>8i Doc Set</Part> <Price>350</Price> </Item> </PurchaseOrder>'));
XML Schemaでは順序の保持についての情報が指定されていないため、デフォルト動作では、順序およびDOM再現性が保持されます。したがって、型には、ノードの順序を保持し、コメントや処理命令などの追加項目を取得するのに必要な追加情報を格納するためのSYS_XDBPD$
(PD)属性が含まれます。
オブジェクト属性SYS_XDBPD$
には、要素の有無を示す情報(入力ドキュメントに要素が存在したかどうか)も保持されます。simpleType
要素の場合は単純なリレーショナル列にマップされるため、この情報が必要です。空のsimpleType
要素と欠落しているsimpleType
要素の両方が列のNULL
値にマップされます。この2つを区別するには、SYS_XDBPD$
属性を使用できます。XPathリライト・メカニズムでは属性SYS_XDBPD$
の有無が考慮され、問合せが適切にリライトされます。
この表には、実際のデータを格納するpurchaseorder_t
という型の疑似列XMLDATA
が含まれます。
この項では、XPath式からSQLデータ型とパス式へのマッピングについて説明します。
XPath式には、要素のテキスト・ノード(コンテンツ)をターゲットとするtext()
ノード・テストを含めることができます。リライトによって、この式は基礎となるリレーショナル列に直接マップされます。たとえば、XPath式/PurchaseOrder/PONum/text()
は、SQL列XMLDATA
."PONum
"に直接マップされます。
PONum
列のNULL
値は、入力ドキュメントにtext()
ノード・テストが存在しないか、または要素自体が欠落しているため、テキスト値が使用できないことを意味します。列がNULL
の場合、SYS_XBDPD$
属性で要素の有無を確認する必要はありません。
XPath /PurchaseOrder/PONum
も、SQL列XMLDATA."PONum"
にマップされます。ただし、この場合、XPathリライトで、XMLDATA
列のSYS_XDBPD$
属性を使用して要素自体の有無を確認する必要があります。
XPath述語は、SQL述語式にマップされます。比較では、XPath 1.0セマンティクスにでなくSQLの比較規則が使用されます。「XPathリライトによる比較セマンティクスの変更」を参照してください。
たとえば、XPath式/PurchaseOrder[PONum=1001 and Company = "Oracle Corp"]
の述語はSQL述語(XMLDATA."PONum" = 20 AND XMLDATA."Company" = "Oracle Corp")
にマップされます。
例7-8 述語のマッピング
この問合せは、構造化された(オブジェクト・リレーショナルな)問合せにリライトされます。
SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Item').getCLOBval() FROM mypurchaseorders p WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[PONum=1001 AND Company = "Oracle Corp"]') = 1;
コレクション述語のマッピングXPath式に、リレーショナル・コレクション式が含まれていることがあります。Xpath 1.0では、これらの式は要素の有無の確認として処理されます。少なくとも1つのコレクション・メンバーが式に含まれている場合、その式はtrueです。
例7-9 コレクション述語のマッピング
このXPath式のコレクション述語には、リレーショナルの大なり演算子(>
)が含まれています。
/PurchaseOrder[Items/Price > 200]
これは、次のSQLコレクション式にマップされます。
exists(SELECT NULL FROM table(XMLDATA."Item") x WHERE x."Price" > 200)
この例では、コレクションがスカラー値に関連付けられています。2つのコレクションに関連がある場合、リライトは複雑になります。たとえば、次のXPath式では、LineItems
とShippedItems
はいずれもコレクションです。
/PurchaseOrder[LineItems = ShippedItems]
この場合、この2つのコレクションからのノードのいずれかの組合せが等価性を満たしていれば、その述語が等価性を満たしていると判断されます。
例7-10 EXISTSNODEを使用したコレクション述語のマッピング
Purchaseorder
にPrice
とPart
の数値が同じであるItem
が存在するかどうかを確認するXPath、/PurchaseOrder[Items/Price = Items/Part]
を考えてみます。これは、次のSQLコレクション式にマップされます。
EXISTS (SELECT NULL FROM table(XMLDATA."Item") x WHERE EXISTS (SELECT NULL FROM table(XMLDATA."Item") y WHERE y."Part" = x."Price"))
次の問合せは、構造化された問合せにリライトされます。
SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Item').getCLOBval() FROM mypurchaseorders p WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Item/Price = Item/Part]') = 1;
ほとんどのリライトでは、元のドキュメント内の順序が保持されます。ただし、SQLでは副問合せの結果における順序の保持が保証されないため、SQL関数extract
を使用してコレクションから要素を選択すると、ノードの順序がドキュメント内の順序と異なる場合があります。
例7-11 コレクション全検索でのドキュメント内の順序の保持
次に例を示します。
SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Item[Price>2100]/Part') FROM mypurchaseorders p;
この問合せは、副問合せを使用するようにリライトされます。
SELECT (SELECT XMLAgg(XMLForest(x."Part" AS "Part")) FROM table(XMLDATA."Item") x WHERE x."Price" > 2100) FROM mypurchaseorders p;
ほとんどの場合、集計の結果はコレクション要素と同じ順序になりますが、これが保証されているわけではありません。したがって、結果がドキュメント順序とは異なる場合もあります。
XPath式で、コレクションの特定位置にある要素にアクセスすることもできます。たとえば、/PurchaseOrder/Item[1]/Part
は、コレクションの最初のItem
を抽出し、その中のPart
属性にアクセスするようにリライトされます。
コレクションがVARRAY値として格納されている場合は、この操作によって元のドキュメント内の順序でノードが取得されます。コレクションが順序付けられていない表に格納されている場合、順序は判別不能です。
XPath式には、入力ドキュメントに含めることができないノードに対する参照が含まれる場合があります。式のこのような部分は、リライト時にSQLのNULL
値にマップされます。たとえば、/PurchaseOrder/ShipAddress
というXPath式は、purchaseorder.xsd
というXML Schemaに準拠するインスタンス・ドキュメントの条件を満たすことができません。これは、スキーマでPurchaseOrder
のShipAddress
要素が許可されないためです。したがって、この式はSQLのNULL
リテラルにマップされます。
名前空間は、関数ベースの評価と同じ方法で処理されます。XML Schemaに基づく文書の場合、関数(existsNode
やextract
など)によって名前空間パラメータが指定されないと、スキーマのターゲットの名前空間がXPath式のデフォルトの名前空間として使用されます。
例7-12 名前空間の処理
たとえば、SQL関数によって名前空間の接頭辞およびマッピングが明示的に指定されない場合、XPath式/PurchaseOrder/PONum
は、xmlns:a= "http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd
で/a:PurchaseOrder/a:PONum
として処理されます。別の例を示します。
SELECT * FROM mypurchaseorders p WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder/PONum') = 1;
これは、次の問合せと同等の結果を戻します。
SELECT * FROM mypurchaseorders p WHERE existsNode( OBJECT_VALUE, '/PurchaseOrder/PONum', 'xmlns="http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd') = 1;
XPathリライトを実行すると、特定の要素に対する名前空間はXML Schema定義の名前空間と一致します。XML SchemaにelementFormDefault = "qualified"
が含まれる場合、XPath式の各ノードは名前空間をターゲットとする必要があります(これは、デフォルトの名前空間の指定を使用するか、または各ノードに名前空間の接頭辞を付けることで実行できます)。
elementFormDefault
が非修飾(デフォルト)である場合、名前空間を定義するノードのみに接頭辞が含まれる必要があります。たとえば、purchaseorder.xsd
の要素形式が非修飾の場合は、existsNode
式を次のようにリライトする必要があります。
existsNode( OBJECT_VALUE, '/a:PurchaseOrder/PONum', 'xmlns:a="http://xmlns.oracle.com/xdb/documentation/purchaseOrder.xsd") = 1;
注意: elementFormDefault が非修飾である場合、前述の例のexistsNode 式で名前空間パラメータを省略すると、各ノードがデフォルトでターゲットの名前空間に設定されます。これは、XML Schema定義に一致しないために、結果が戻されない場合があります。これは、関数がリライトされるかどうかに関係ありません。 |
date
、gMonth
およびgDate
の日付データ型の書式は、XML SchemaとSQLで異なります。このようなデータ型の列に対する文字列値が式に含まれていると、リライトによってXML形式の文字列が自動的に挿入され、文字列値が正しく変換されます。このため、date
列に指定された文字列値は、SQLのDATE
書式ではなく、XMLのdate
書式に一致している必要があります。
例7-13 日付書式の変換
たとえば、式[@PurchaseDate="2002-02-01"]
は単にXMLDATA."PurchaseDate"="2002-02-01"
としてはリライトされません。これは、SQLのデフォルトの日付書式がYYYY-MM-DD
でないためです。したがって、XPathのリライト時に、XML形式の文字列が追加され、テキスト値がDATEデータ型に正しく変換されます。前述の述語は、次のとおりリライトされます。
XMLDATA."PurchaseDate" = TO_DATE("2002-02-01","SYYYY-MM-DD");
同様に、これらの列を(extract
などの関数に必要な)テキスト値に変換する際に、XML形式の文字列が追加されてXMLと同じ日付書式に変換されます。
SQL関数existsNode
は、XPathで指定されているノードの有無を確認します。関数extract
は、XPathで指定されているノードを戻します。Oracle XML DBは、simpleType
要素に対して、およびexistsNode
式で使用されている属性に対して、特別なチェックを実行する必要があります。これは、SQL列の値が単独では属性またはsimpleType
要素が欠落していたり、空であることを識別できないためです。NULL
のSQL列は、いずれも表すことができます。中間要素の場合は、ユーザー定義のSQLデータ型によって、その要素が欠落していること、または空であることが示されるため、これらの特別なチェックは不要です。
たとえば、次の式について考えてみます。
existsNode(OBJECT_VALUE, '/PurchaseOrder/PONum/text()') = 1;
問合せがノードのテキスト値のみを対象としているため、この式は次のようにリライトされます。
(p.XMLDATA."PONum" IS NOT NULL)
次に、text()
ノード・テストのない式について考えてみます。
existsNode(OBJECT_VALUE, '/PurchaseOrder/PONum') = 1;
この場合、Oracle XML DBは、親ノードのSYS_XDBPD$
属性をチェックして、要素が空または欠落しているかどうかを判断する必要があります。このチェックは内部で実行されます。これは、次のような擬似コードで表すことができます。
node_exists(p.XMLDATA."SYS_XDBPD$", "PONum")
擬似関数node_exists
は、説明のためのみに使用しています。これは、最初の引数である位置指定ディスクリプタ(PD)列(SYS_XDBPD$
)を使用して2番目の引数(要素または属性)のノードが存在するかどうかを判別する、Oracle XML DBの実装を表しています。2番目の引数のノードが存在する場合はtrueを、存在しない場合はfalseを戻します。
extract
式の場合は、属性および要素の両方に対してこのチェックを実行する必要があります。extract(OBJECT_VALUE, '/PurchaseOrder/PONum')
という形式の式は、次のような擬似コードにマップされます。
CASE WHEN node_exists(p.XMLDATA.SYS_XDBPD$", "PONum")
THEN XMLElement("PONum", p.XMLDATA."PONum")
ELSE NULL END;
注意: existsNode またはextract 式を記述する場合は、このオーバーヘッドに注意してください。このオーバーヘッドを回避するには、XPath式のtext() ノード・テストを使用するか、extractValue を使用してノードの値のみを取得するか、あるいは親ノードのDOM再現性を無効にします。DOM再現性は、要素定義のmaintainDOM 属性の値をfalse に設定することで無効にできます。無効にした場合、空の要素および属性は欠落しているとして処理されます。 |
この項では、XPath式が実際にリライトされているかどうかを判断するテクニックを紹介します。
この項では、EXPLAIN PLAN
を使用して、XPathリライト後に問合せ計画を調べる方法について説明します。EXPLAIN PLAN
を使用してXPathリライトを最適化する方法の詳細は、「XPathリライトの理解および最適化」を参照してください。
問合せ評価計画で、適用可能な索引が選択されずにSQL関数(existsNode
、extract
など)の存在が示された場合は、リライトが発生しなかったことがわかります。その後、イベントを使用して、XPathリライトが発生しなかった理由を理解できます。「XPathでのイベントの使用」を参照してください。
たとえば、表mypurchaseorders
を使用して、EXPLAIN PLAN
の使用を確認できます。PurchaseOrder
のCompany
要素に対して索引を作成し、計画の違いを確認します。
CREATE INDEX company_index ON mypurchaseorders (extractValue(OBJECT_VALUE,'/PurchaseOrder/Company')); Index created. EXPLAIN PLAN FOR SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') FROM mypurchaseorders WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Company="Oracle"]') = 1; Explained. SELECT PLAN_TABLE_OUTPUT FROM table(DBMS_XPLAN.display('plan_table', NULL, 'serial')) / PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost | ------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | | | 1 | TABLE ACCESS BY INDEX ROWID | MYPURCHASEORDERS | | | | |* 2 | INDEX RANGE SCAN | COMPANY_INDEX | | | | ------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("MYPURCHASEORDERS"."SYS_NC00010$"='Oracle')
このEXPLAIN PLANでは、述語が内部列を使用しており、Company
要素に対する索引を選択していることを確認できます。これは、問合せが基礎となるリレーショナル列にリライトされたことを示しています。
次の問合せは、文字列型であるCompany
要素に対して算術演算を実行しようとしています。これはリライトされません。EXPLAIN PLAN
は述語に元のexistsNode
式が含まれていることを示しています。また、述語はリライトされないため、索引レンジ・スキャンではなく、全表スキャンが使用されます。
EXPLAIN PLAN FOR SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') FROM mypurchaseorders WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Company+PONum="Oracle"]') = 1; Explained. SELECT PLAN_TABLE_OUTPUT FROM table(DBMS_XPLAN.display('plan_table', NULL, 'serial'))/ PLAN_TABLE_OUTPUT ----------------------------------------------------------- | Id | Operation | Name ----------------------------------------------------------- | 0 | SELECT STATEMENT | |* 1 | FILTER | | 2 | TABLE ACCESS FULL| MYPURCHASEORDERS |* 3 | TABLE ACCESS FULL| ITEM_NESTED ----------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(EXISTSNODE(SYS_MAKEXML('C6DB2B4A1A3B0 6CDE034080020E5CF39',2300,"MYPURCHASEORDERS"."XMLEXTRA", "MYPURCHASEORDERS"."XMLDATA"), '/PurchaseOrder[Company+PONum="Oracle"]')=1) 3 - filter("NESTED_TABLE_ID"=:B1)
イベントは、初期化ファイルに設定するか、またはALTER SESSION
文を使用して各セッションに設定できます。XMLイベントを使用すると、機能上の評価やXPathリライト・メカニズムを無効にしたり、診断トレースを印刷できます。
このイベントを使用可能にすることで、XML関数がリライトされずに機能上の評価が行われる場合には、常にエラーが発行されるようにできます。このような関数が実行されると、エラー「ORA-19022: XML XPath機能は使用できません」が発行されます。また、このイベントを使用して、関数に対する機能上の評価を選択して無効にすることもできます。表7-3に、様々なイベント・レベルおよび対応する動作をリストします。
表7-3 イベントのレベルおよび動作
イベント | 機能上の評価が無効になる関数 |
---|---|
レベル0x1 |
すべてのXML関数 |
レベル0x2 |
|
レベル0x4 |
|
レベル0x8 |
|
レベル0x10 |
|
レベル0x20 |
|
レベル0x40 |
|
レベル0x80 |
|
レベル0x100 |
|
レベル0x200 |
|
レベル0x4000 |
|
レベル0x8000 |
|
次に例を示します。
ALTER SESSION SET EVENTS '19021 trace name context forever, level 1';
この場合、前述のすべてのXML演算子の評価が無効になります。したがって、リライトされていない前述の問合せを実行すると、問合せの実行でエラーが発生します。
SELECT OBJECT_VALUE FROM mypurchaseorders WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Company+PONum="Oracle"]')=1 ; ERROR: ORA-19022: XML XPath functions are disabled
8192
(0x2000)レベルのイベント19027
を使用すると、特定のXML関数がリライトされていない理由を示すトレースをダンプできます。たとえば、前述の問合せがリライトされなかった理由を調べる場合は、イベントを設定してEXPLAIN PLAN
を実行します。
ALTER SESSION SET EVENTS '19027 TRACE NAME CONTEXT FOREVER, LEVEL 8192'; Session altered. EXPLAIN PLAN FOR SELECT OBJECT_VALUE FROM mypurchaseorders WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Company+100="Oracle"]') = 1; Explained.
次の記述は、算術関数に対する数値以外の入力が原因でXPathのリライトが生じなかったことを示すOracleのトレース・ファイルです。
NO REWRITE XPath ==> /PurchaseOrder[Company+PONum = "Oracle"] Reason ==> non numeric inputs to arith{2}{4}
この項では、SQL関数existsNode
、extractValue
、extract
、XMLSequence
、updateXML
、insertChildXML
およびdeleteXML
に対するXPathリライトについて詳しく説明します。existsNode
またはextract
を使用する特定タイプの操作で発生するオーバーヘッドと、それを回避する方法について説明します。
これらのSQL関数を使用する更新では、通常、XML文書のコピーが更新されてから、新しく変更された文書で文書全体が置換されます。
XMLType
データがXML Schemaマッピングを使用してオブジェクト・リレーショナル形式で格納されている場合は、文書の断片がインプレース変更されるように更新が最適化されます。たとえば、PONum
要素を更新する場合、メモリー内で文書全体を生成した後に更新を実行するのではなく、列XMLDATA."PONum"
が直接更新されるようにリライトできます。
更新時にこのようなリライト最適化を使用するには、関数updateXML
、insertChildXML
およびdeleteXML
がそれぞれ別の条件を満たしている必要があります。前述のすべての条件が満たされる場合、ファンクション式は単純なリレーショナル更新にリライトされます。次に例を示します。
UPDATE purchaseorder_table SET OBJECT_VALUE = updateXML(OBJECT_VALUE, '/PurchaseOrder/@PurchaseDate', '2002-01-02', '/PurchaseOrder/PONum/text()', 2200);
この更新操作は、次のようにリライトされます。
UPDATE purchaseorder_table p SET p.XMLDATA."PurchaseDate" = TO_DATE('2002-01-02', 'SYYYY-MM-DD'), p.XMLDATA."PONum" = 2100;
XPath引数が空でないノード(テキスト、要素または属性)のシーケンスをターゲットにしている場合、SQL関数existsNode
は1
を戻します。そうでない場合は、0
(ゼロ)を戻します。値の判別方法は、XPath引数でターゲットになっているノードの種類によって異なります。
XPath引数が(ノード・テストtext()
を使用する)テキスト・ノードまたはcomplexType
要素ノードをターゲットにしている場合、Oracle XML DBは、要素のコンテンツのデータベース表示がNULL
であるかどうかをチェックするのみです。
それ以外の場合、XPath引数はsimpleType
要素ノードまたは属性ノードをターゲットにしています。Oracle XML DBは、位置指定ディスクリプタ属性SYS_XDBPD$
を使用してノードの有無を確認します。SYS_XDBPD$
属性が存在しない場合は、列がNULL
かどうかを調べることによってノードの有無が判断されます。
表7-4に、ドキュメント内の順序が保持される(SYS_XDBPD$
が存在し、スキーマ・ドキュメントでmaintainDOM = "true"
が設定されている)場合の、SQL関数existsNode
での様々なXPath式のマッピングを示します。
表7-4 ドキュメント内の順序が保持されるEXISTSNODEのXPathマッピング
XPath式 | マップ先 |
---|---|
/PurchaseOrder |
CASE WHEN XMLDATA IS NOT NULL THEN 1 ELSE 0 END |
/PurchaseOrder/@PurchaseDate |
CASE WHEN node_exists脚注1 (XMLDATA.SYS_XDBPD$, 'PurchaseDate') THEN 1 ELSE 0 END |
/PurchaseOrder/PONum |
CASE WHEN node_exists脚注1(XMLDATA.SYS_XDBPD$, 'PONum') THEN 1 ELSE 0 END |
/PurchaseOrder[PONum = 2100] |
CASE WHEN XMLDATA."PONum"=2100 THEN 1 ELSE 0 |
/PurchaseOrder[PONum = 2100]/@PurchaseDate |
CASE WHEN XMLDATA."PONum"=2100 AND node_exists脚注1(XMLDATA.SYS_XDBPD$, 'PurchaseDate') THEN 1 ELSE 0 END |
/PurchaseOrder/PONum/text() |
CASE WHEN XMLDATA."PONum" IS NOT NULL THEN 1 ELSE 0 |
/PurchaseOrder/Item |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x WHERE value(x) IS NOT NULL) THEN 1 ELSE 0 END |
/PurchaseOrder/Item/Part |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x WHERE node_exists脚注1(x.SYS_XDBPD$, 'Part')) THEN 1 ELSE 0 END |
/PurchaseOrder/Item/Part/text() |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x WHERE x."Part" IS NOT NULL) THEN 1 ELSE 0 END |
脚注1 擬似関数node_exists
は、説明のためのみに使用しています。これは、最初の引数であるPD列を使用して2番目の引数のノードが存在するかどうかを判断する、Oracle XML DBの実装を表しています。2番目の引数のノードが存在する場合はtrueを、存在しない場合はfalseを戻します。
例7-14 ドキュメント内の順序が保持されるEXISTSNODEのマッピング
この問合せでは、前述のマッピングを使用して、発注1001に価格が2000を超える部品が存在するかどうかを確認します。
SELECT count(*) FROM purchaseorder WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[PONum=1001 and Item/Price > 2000]') = 1;
この問合せは、次のようにリライトされます。
SELECT count(*) FROM purchaseorder p WHERE CASE WHEN p.XMLDATA."PONum" = 1001 AND exists(SELECT NULL FROM table(XMLDATA."Item") p WHERE p."Price" > 2000 )) THEN 1 ELSE 0 END = 1;
このCASE
式は、さらに定数関係式によって最適化されます。問合せは、次のように再作成されます。
SELECT count(*) FROM purchaseorder p WHERE p.XMLDATA."PONum"=1001 AND exists(SELECT NULL FROM table(p.XMLDATA."Item") x WHERE x."Price" > 2000);
Part
列およびPONum
列にリレーショナル索引が存在する場合、そのリレーショナル索引を使用して評価が行われます。
位置指定ディスクリプタ属性SYS_XDBPD$
が存在しない場合(つまり、XML SchemaでmaintainDOM = "false"
が指定されている場合)、NULL
スカラー列が、存在しないsimpleType
要素にマップされます。その場合、属性SYS_XDBPD$
を使用してノードの有無を確認する必要はありません。表7-5に、SYS_XDBPD$
属性がない場合のexistsNode
のマッピングを示します。
表7-5 ドキュメント内の順序が保持されないEXISTSNODEのXPathマッピング
XPath式 | マップ先 |
---|---|
/PurchaseOrder |
CASE WHEN XMLDATA IS NOT NULL THEN 1 ELSE 0 END |
/PurchaseOrder/@PurchaseDate |
CASE WHEN XMLDATA.'PurchaseDate' IS NOT NULL THEN 1 ELSE 0 END |
/PurchaseOrder/PONum |
CASE WHEN XMLDATA."PONum" IS NOT NULL THEN 1 ELSE 0 END |
/PurchaseOrder[PONum = 2100] |
CASE WHEN XMLDATA."PONum" = 2100 THEN 1 ELSE 0 END |
/PurchaseOrder[PONum = 2100]/@PurchaseOrderDate |
CASE WHEN XMLDATA."PONum" = 2100 AND XMLDATA."PurchaseDate" NOT NULL THEN 1 ELSE 0 END |
/PurchaseOrder/PONum/text() |
CASE WHEN XMLDATA."PONum" IS NOT NULL THEN 1 ELSE 0 END |
/PurchaseOrder/Item |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x WHERE value(x) IS NOT NULL) THEN 1 ELSE 0 END |
/PurchaseOrder/Item/Part |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x WHERE x."Part" IS NOT NULL) THEN 1 ELSE 0 END |
/PurchaseOrder/Item/Part/text() |
CASE WHEN exists(SELECT NULL FROM table(XMLDATA."Item") x WHERE x."Part" IS NOT NULL) THEN 1 ELSE 0 END |
SQL関数extractValue
は、関数extract
を使用してテキスト・ノードおよび属性を抽出し、次にメソッドgetStringVal()
またはgetNumberVal()
を使用してスカラー・コンテンツを取得するためのショートカットです。関数extractValue
は、スカラー値を持つ要素の属性ノードまたはテキスト・ノードの値を戻します。関数extractValue
は、複数の値またはcomplexType
要素を戻すXPath式を処理できません。
表7-6に、関数extractValue
での様々なXPath式のマッピングを示します。XPath式が要素をターゲットとしている場合は、extractValue
によって要素のテキスト・ノードが取得されます。たとえば、/PurchaseOrder/PONum
および/PurchaseOrder/PONum/text()
はextractValue
によって同じ方法で処理されます。どちらも、PONum
のスカラー・コンテンツを取得します。
XPath式 | マップ先 |
---|---|
/PurchaseOrder |
サポートされていません。関数 |
/PurchaseOrder/@PurchaseDate |
XMLDATA."PurchaseDate" |
/PurchaseOrder/PONum |
XMLDATA."PONum" |
/PurchaseOrder[PONum = 2100] |
(SELECT TO_XML(x.XMLDATA) FROM DUAL WHERE x."PONum" = 2100) |
/PurchaseOrder[PONum = 2100]/@PurchaseDate |
(SELECT x.XMLDATA."PurchaseDate") FROM DUAL WHERE x."PONum" = 2100) |
/PurchaseOrder/PONum/text() |
XMLDATA."PONum" |
/PurchaseOrder/Item |
サポートされていません。関数 |
/PurchaseOrder/Item/Part |
サポートされていません。関数 |
/PurchaseOrder/Item/Part/text() |
サポートされていません。関数 |
例7-15 EXTRACTVALUEのリライト
次のSQL問合せについて考えてみます。
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') FROM purchaseorder WHERE extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') = 1001;
この問合せは、次のようにリライトされます。
SELECT p.XMLDATA."PONum" FROM purchaseorder p WHERE p.XMLDATA."PONum" = 1001;
これは単純なスカラー列にリライトされるため、属性PONum
に対する索引があれば、問合せの条件を満たすためにそれを使用できます。
EXTRACTVALUEを使用した索引の作成
関数extractValue
は、索引式で使用できます。式がスカラー列にリライトされると、索引はファンクション索引ではなくBツリー索引に変換されます。
例7-16 EXTRACTVALUEを使用した索引の作成
CREATE INDEX my_po_index ON purchaseorder (extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference);
これは、次のようにリライトされます。
CREATE INDEX my_po_index ON purchaseorder x (x.XMLDATA."Reference");
これによって、通常のBツリー索引が生成されます。ファンクション索引とは異なり、同じ索引で次のような列をターゲットとする問合せの条件を満たすことができるようになります。
existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;
SQL関数extract
は、XPathの結果をXMLとして取得します。テキスト・ノードが含まれるXpath式の場合、extract
は同様にextractValue
にリライトされます。
表7-7に、ドキュメント内の順序が保持される場合(SYS_XDBPD$
が存在し、XML SchemaドキュメントでmaintainDOM = "true"
が設定されている場合)の、extract
式内部の様々なXPath式のマッピングを示します。
表7-7 ドキュメント内の順序が保持されるEXTRACTのXPathマッピング
XPath | マップ先 |
---|---|
/PurchaseOrder |
XMLForest(XMLDATA AS "PurchaseOrder") |
/PurchaseOrder/@PurchaseDate |
CASE WHEN node_exists脚注1 (XMLDATA.SYS_XDBPD$, 'PurchaseDate') THEN XMLElement("", XMLDATA."PurchaseDate") ELSE NULL END; |
/PurchaseOrder/PONum |
CASE WHEN node_exists脚注1(XMLDATA.SYS_XDBPD$, 'PONum') THEN XMLElement("PONum", XMLDATA."PONum") ELSE NULL END |
/PurchaseOrder[PONum = 2100] |
SELECT XMLForest(XMLDATA as "PurchaseOrder") FROM DUAL WHERE XMLDATA."PONum" = 2100 |
/PurchaseOrder [PONum = 2100]/@PurchaseDate |
SELECT CASE WHEN node_exists脚注1(XMLDATA.SYS_XDBPD$, 'PurchaseDate') THEN XMLElement("", XMLDATA."PurchaseDate") ELSE NULL END FROM DUAL WHERE XMLDATA."PONum" = 2100 |
/PurchaseOrder/PONum/text() |
XMLElement("", XMLDATA."PONum") |
/PurchaseOrder/Item |
SELECT XMLAgg(XMLForest(value(it) AS "Item")) FROM table(XMLDATA."Item") it |
/PurchaseOrder/Item/Part |
SELECT XMLAgg(CASE WHEN node_exists脚注1(p.SYS_XDBPD$, 'Part') THEN XMLForest(p."Part" AS "Part") ELSE NULL END) FROM table(XMLDATA."Item") p |
/PurchaseOrder/Item/Part/text() |
SELECT XMLAgg(XMLElement("", p."Part")) FROM table(XMLDATA."Item") p |
脚注1 擬似関数node_exists
は、説明のためのみに使用しています。これは、最初の引数であるPD列を使用して2番目の引数のノードが存在するかどうかを判断する、Oracle XML DBの実装を表しています。2番目の引数のノードが存在する場合はtrueを、存在しない場合はfalseを戻します。
例7-17 ドキュメント内の順序が保持されるEXTRACTのXPathマッピング
表7-7に示すマッピングを使用して、発注書に価格が2000を超える部品が含まれるPONum
要素を抽出する次の問合せを考えてみます。
SELECT extract(OBJECT_VALUE, '/PurchaseOrder[Item/Part > 2000]/PONum') FROM purchaseorder_table;
この問合せは、次のようになります。
SELECT (SELECT CASE WHEN node_exists(p.XMLDATA.SYS_XDBPD$, 'PONum')
THEN XMLElement("PONum", p.XMLDATA."PONum")
ELSE NULL END
FROM DUAL
WHERE exists(SELECT NULL FROM table(XMLDATA."Item") p
WHERE p."Part" > 2000))
FROM purchaseorder_table p;
属性SYS_XDBPD$
が存在しない場合(つまり、XML SchemaでmaintainDOM = "false"
が指定されている場合)、NULL
スカラー列が、存在しないsimpleType
要素にマップされます。したがって、属性SYS_XDBPD$
を使用してノードの有無を確認する必要はありません。表7-8に、SYS_XDBPD$
がない場合の関数existsNode
のマッピングを示します。
表7-8 ドキュメント内の順序が保持されないEXTRACTのXPathマッピング
XPath | マップ先 |
---|---|
/PurchaseOrder |
XMLForest(XMLDATA AS "PurchaseOrder") |
/PurchaseOrder/@PurchaseDate |
XMLForest(XMLDATA."PurchaseDate" AS "PurchaseDate") |
/PurchaseOrder/PONum |
XMLForest(XMLDATA."PONum" AS "PONum") |
/PurchaseOrder[PONum = 2100] |
SELECT XMLForest(XMLDATA AS "PurchaseOrder") FROM DUAL WHERE XMLDATA."PONum" = 2100 |
/PurchaseOrder [PONum = 2100]/@PurchaseDate |
SELECT XMLForest(XMLDATA."PurchaseDate" AS "PurchaseDate "") FROM DUAL WHERE XMLDATA."PONum" = 2100 |
/PurchaseOrder/PONum/text() |
XMLForest(XMLDATA.PONum AS "") |
/PurchaseOrder/Item |
SELECT XMLAgg(XMLForest(value(p) AS "Item") FROM table(XMLDATA."Item") p |
/PurchaseOrder/Item/Part |
SELECT XMLAgg(XMLForest(p."Part" AS "Part") FROM table(XMLDATA."Item") p |
/PurchaseOrder/Item/Part/text() |
SELECT XMLAgg(XMLForest(p. "Part" AS "Part")) FROM table(XMLDATA."Item") p |
SQL関数XMLSequence
をSQL関数extract
およびtable
と組み合せて使用すると、XMLのコレクション値をネスト解除できます。脚注1 XML Schemaに基づく記憶域で使用されている場合、これらの関数も、基礎となるリレーショナル・コレクション記憶域にアクセスするようにリライトされます。
たとえば、この問合せは、全品目の価格と部品番号をリレーショナル形式で取得します。
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') AS ponum, extractValue(value(it), '/Item/Part') AS part, extractValue(value(it), '/Item/Price') AS price FROM purchaseorder, table(XMLSequence(extract(OBJECT_VALUE, '/PurchaseOrder/Item'))) it; PONUM PART PRICE ----- -------------------- --------- 1001 9i Doc Set 2550 1001 8i Doc Set 350
この例では、SQL関数extract
は、Item
要素のリストを含むフラグメントを戻します。関数XMLSequence
は、Item
要素ごとに、このフラグメントをXMLType
値のコレクションに変換します。関数table
は、コレクションの要素をXMLType
の行に変換します。table
から戻されたXMLデータは、Part
要素およびPrice
要素の抽出に使用されます。
関数extract
およびXMLSequence
を適用すると、Ordered Collection Table(OCT)のitem_nested
上の単純なSELECT
操作にリライトされます。
EXPLAIN PLAN FOR SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') AS ponum, extractValue(value(it) , '/Item/Part') AS part, extractValue(value(it), '/Item/Price') AS price FROM purchaseorder, table(XMLSequence(extract(OBJECT_VALUE, '/PurchaseOrder/Item'))) it; Explained PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------- | Id | Operation | Name | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | NESTED LOOPS | | | 2 | TABLE ACCESS FULL | ITEM_NESTED | | 3 | TABLE ACCESS BY INDEX ROWID | PURCHASEORDER | |* 4 | INDEX UNIQUE SCAN | SYS_C002973 | ---------------------------------------------------------------------------- Predicate Information (identified by operation id) -------------------------------------------------- 4 - access("NESTED_TABLE_ID"="SYS_ALIAS_1"."SYS_NC0001100012$")
EXPLAIN PLAN
の出力は、オプティマイザがOCTのitem_nested
と表purchaseorder
との間の単純なネステッド・ループ結合を使用できることを示しています。Item
値をさらに問い合せたり、OCTに適切な索引を作成して問合せを高速化することもできます。
たとえば、価格を検索して高価な品目すべてを取得するには、OCTのPrice
列に対して索引を作成します。次のEXPLAIN PLAN
は、価格索引を使用して品目のリストを取得し、表purchaseorder
と結合してPONum
値を取得します。
CREATE INDEX price_index ON item_nested ("Price");
Index created.
EXPLAIN PLAN FOR
SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/PONum') AS ponum,
extractValue(value(it), '/Item/Part') AS part,
extractValue(value(it), '/Item/Price') AS price
FROM purchaseorder,
table(XMLSequence(extract(OBJECT_VALUE, '/PurchaseOrder/Item'))) it
WHERE extractValue(value(it), '/Item/Price') > 2000;
Explained.
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------
| Id | Operation | Name |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | NESTED LOOPS | |
| 2 | TABLE ACCESS BY INDEX ROWID | ITEM_NESTED |
|* 3 | INDEX RANGE SCAN | PRICE_INDEX |
| 4 | TABLE ACCESS BY INDEX ROWID | PURCHASEORDER |
|* 5 | INDEX UNIQUE SCAN | SYS_C002973 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ITEM_NESTED"."Price">2000)
5 - access("NESTED_TABLE_ID"="SYS_ALIAS_1"."SYS_NC0001100012$")
SQL関数updateXML
で最適化を使用するには、次の条件を満たす必要があります。
XMLType
引数が登録済のXML Schemaに基づいていること。
XMLType
引数がUPDATE
操作のターゲットにもなっていること。次に例を示します。
UPDATE purchaseorder_table SET OBJECT_VALUE = updateXML(OBJECT_VALUE,...);
XPath引数がすべて異なっていること(重複がない)。
「リライトされるXPath式」で説明されているとおり、XPath引数がリライト可能であること。
XML SchemaでmaxOccurs <= 1
を使用してマップされた要素をターゲットとするXPath引数は、スキーマ注釈maintainDom = false
が存在する場合にのみリライトされます。
XPath引数が、(XML Schemaで定義されているように)デフォルト値を持つノードをターゲットにしていないこと。
XPath引数が位置指定述語(たとえば、foo[2]
など)を持たないこと。
XPath引数に述語が含まれる場合、述語がコレクションより前に出現しないこと。
たとえば、/PurchaseOrder/LineItems[@MyAtt="3"]/LineItem
は、述語がLineItem
コレクションよりも出現するため、リライトされません。(これは、LineItems
が属性MyAtt
を持つXML Schemaを想定しています。)
XPath式の引数がコレクションを参照している場合、そのコレクションが、個別のOrdered Collection Tableとして格納されているか、または表外(REF
記憶域)に格納されていること(つまり表内に格納されていないこと)。
XPath引数がコレクションを参照している場合、そのコレクションがスカラー(maxOccurs > 1
であるsimpleType
)でないこと。
SQL関数deleteXML
で最適化を使用するには、次の条件を満たす必要があります。
XMLType
引数が登録済のXML Schemaに基づいていること。
XMLType
引数がUPDATE
操作のターゲットにもなっていること。次に例を示します。
UPDATE purchaseorder_table SET OBJECT_VALUE = updateXML(OBJECT_VALUE,...);
「リライトされるXPath式」で説明されているとおり、XPath引数がリライト可能であること。
XPath引数が位置指定述語(たとえば、foo[2]
)を持たないこと。
XPath引数に述語が含まれる場合、述語がコレクションより前に出現しないこと。
たとえば、/PurchaseOrder/LineItems[@MyAtt="3"]/LineItem
は、述語がLineItem
コレクションよりも出現するため、リライトされません。(これは、LineItems
が属性MyAtt
を持つXML Schemaを想定しています。)
XPath引数が無制限のコレクション(maxOccurs = "unbounded"
が指定された要素)をターゲットにしていること。
XPath引数が、XML Schemaで定義されているように、コレクションのchoice
をターゲットにしていないこと。
ターゲットになっているコレクションの親が、XML Schema内で注釈maintainDOM = "false"
を使用して定義されていること。
XPath引数がコレクションを参照している場合、そのコレクションが、表外(REF
記憶域)でも表内でもなく個別のOrdered Collection Tableとして格納されていること。
XPath引数がコレクションを参照している場合、そのコレクションがスカラー(maxOccurs > 1
であるsimpleType
)でないこと。
脚注の凡例
脚注1: 関数table
とXMLSequence
を使用するかわりに、よりわかりやすい標準のSQL/XML関数XMLTable
を使用することもできます。