ヘッダーをスキップ
Oracle XML DB開発者ガイド
11gリリース1(11.1)
E05669-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

4 XMLTypeの操作

この章では、XMLアプリケーションに対するXMLTypeの操作(XML Schemaに基づく、およびXML Schemaに基づかない)について説明します。XMLType列および表の作成、操作、更新、および問合せに関するガイドラインも含まれています。

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


関連項目:


XMLデータの選択および問合せ

次の方法で、XMLType列からXMLデータを問い合せることができます。

XPath式を使用したXML文書の検索

XPath言語は、XML文書をナビゲートするためのW3C勧告です。XPathは、XML文書をノードのツリーとしてモデル化します。XPathには、このツリー内を移動し、述語およびノード・テスト関数を適用するための豊富な操作が備わっています。XPath式をXML文書に適用すると、ノードの集合が戻されます。たとえば、式/PO/PONOは、文書のPOルート要素の下にあるすべてのPONO子要素を選択します。


注意:

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

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


表4-1に、XPathで使用する共通構造体を示します。

表4-1 XPathの共通構造体

XPath構造体 説明

/


XPath式のツリーのルートを示します。たとえば、/POは、名前がPOであるルート・ノードの子を示します。

/


任意のノードの子ノードを識別するための区切りとしても使用します。たとえば、/PurchaseOrder/Referenceは、ルート要素の子である発注書名要素Referenceを示します。

//


現行ノードのすべての子孫を識別するために使用します。たとえば、PurchaseOrder//ShippingInstructionsは、PurchaseOrder要素の下にあるすべてのShippingInstructions要素と一致します。

*


任意の子ノードと一致させるためのワイルド・カードとして使用します。たとえば、/PO/*/STREETは、PO要素の孫であるすべての「STREET」要素と一致します。

[ ]

述語式を示すために使用します。XPathはORANDNOTなど、様々なバイナリ演算子をサポートしています。たとえば、/PO[PONO=20 AND PNAME="PO_2"]/SHIPADDRは、発注書番号が20で、発注書名がPO_2であるすべての発注書の出荷先要素を選択します。

大カッコは、位置(索引)を示す場合にも使用します。たとえば、/PO/PONO[2]は、POルート要素の下の2番目の発注書番号要素を示します。

関数

XPathは、substring()round()not()などの一連の組込み関数をサポートしています。さらに、XPathでは名前空間を使用することで拡張関数を利用できます。Oracleの名前空間http://xmlns.oracle.com/xdbでは、Oracle XML DBが関数ora:contains()もサポートしています。この関数は、同等のSQL関数と同様に動作します。


XPathは単一のノードまたは一連の要素、テキストまたは属性ノードを識別する必要があります。XPathの結果はブール式にはできません。

OracleのXPath拡張関数のサポート

Oracleは、XPath拡張関数ora:contains()をサポートしています。この関数は、XPathを使用したテキスト検索機能を提供します。

XMLTypeメソッドを使用したXMLデータの選択

XMLTypeデータは、PL/SQL、CまたはJavaを使用して選択できます。XMLTypeメソッドgetCLOBVal()getStringVal()getNumberVal()およびgetBLOBVal(csid)を使用して、XMLデータをそれぞれCLOBVARCHARNUMBERおよびBLOB値として取り出すこともできます。

例4-1 メソッドgetCLOBVal()を使用したXMLType列の選択

この例は、メソッドgetCLOBVal()を使用してXMLType列を選択する方法を示しています。

CREATE TABLE xml_table OF XMLType;

Table created.

CREATE TABLE table_with_xml_column (filename VARCHAR2(64), xml_document XMLType);

Table created.

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

1 row created.

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

1 row created.

SELECT x.OBJECT_VALUE.getCLOBVal() FROM xml_table x;

X.OBJECT_VALUE.GETCLOBVAL()
--------------------------------------------------------------------------------
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNames
paceSchemaLocation="http://localhost:8080/source/schemas/poSource/xsd/purchaseOr
der.xsd">
  <Reference>SBELL-2002100912333601PDT</Reference>
  <Actions>
    <Action>
      <User>SVOLLMAN</User>
    </Action>
  </Actions>
  <Reject/>
  <Requestor>Sarah J. Bell</Requestor>
  <User>SBELL</User>
  <CostCenter>S30</CostCenter>
  <ShippingInstructions>
    <name>Sarah J. Bell</name>
    <address>400 Oracle Parkway
      Redwood Shores
...

1 row selected.

--
SELECT x.xml_document.getCLOBVal() FROM table_with_xml_column x;

X.XML_DOCUMENT.GETCLOBVAL()
--------------------------------------------------------------------------------
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNames
paceSchemaLocation="http://localhost:8080/source/schemas/poSource/xsd/purchaseOr
der.xsd">
  <Reference>SBELL-2002100912333601PDT</Reference>
  <Actions>
    <Action>
      <User>SVOLLMAN</User>
    </Action>
  </Actions>
  <Reject/>
  <Requestor>Sarah J. Bell</Requestor>
  <User>SBELL</User>
  <CostCenter>S30</CostCenter>
  <ShippingInstructions>
    <name>Sarah J. Bell</name>
    <address>400 Oracle Parkway
      Redwood Shores
...

1 row selected.

注意:

XMLTypeメソッドgetCLOBVal()一時CLOB値を戻すことがあります。プログラムによってgetCLOBVal()をコールする場合は、このような一時CLOB値を、使用し終わった時点で明示的に解放する必要があります。解放するには、PL/SQLメソッドDBMS_LOB.freeTemporary()をコールするか、JavaまたはC(OCI)でこれと同等のメソッドをコールします。メソッドDBMS_LOB.isTemporary()を使用すると、CLOB値が一時CLOB値かどうかを調べることができます。

SQL関数を使用したXMLTypeデータの問合せ

次のSQL関数を使用すると、XMLTypeデータを問い合せて一部を抽出できます。

  • SQL/XML標準関数XMLQueryXMLTableXMLExistsおよびXMLCast

  • Oracle関数existsNodeextractおよびextractValue

Oracle関数は、W3CのXPath勧告のサブセットを使用して文書をナビゲートします。XMLQuery関数およびXMLTable関数の詳細は、第18章「Oracle XML DBでのXQueryの使用」を参照してください。他の関数については、次の各項で説明します。

XMLEXISTS SQL関数

図4-1に、SQL/XMLの標準関数XMLExistsの構文を示します。この関数は、所定のXQuery式が空でないXQueryシーケンスを戻すかどうかを確認します。空でない場合、この関数はTRUEを戻します。空の場合はFALSEを戻します。

図4-1 XMLExistsの構文

図4-1の説明が続きます
「図4-1 XMLExistsの構文」の説明

XML_passing_clause::=

xml_passing_clause.gifの説明が続きます
図xml_passing_clause.gifの説明

  • XQuery_stringは完結したXQuery式で、プロローグをリテラル文字列として含む場合があります。XQueryのPASSING句(構文図の中のXML_passing_clause)を使用してバインドするXQuery変数を含むことができます。XMLQuery SQL関数に対して認識されている、事前定義された名前空間接頭辞は、XQuery_stringでも認識されています(「事前定義の名前空間と接頭辞」を参照してください)。

  • XML_passing_clauseはキーワードPASSINGに1つ以上のSQL式(expr)を続けたもので、それぞれXMLTypeインスタンスまたはSQLスカラー・データ型のインスタンスを戻します。1つを除いてすべての式では、その後にASおよびXQuery identifierが続いている必要があります。それぞれのexprの評価結果は、対応するidentifierにバインドされ、続いてXQuery_stringが評価されます。AS句に続いていないexprがあった場合、そのexprの評価結果は、XQuery_stringを評価する際のコンテキスト項目として使用されます。Oracle XML DBではBY VALUEを渡すことはできますが、BY REFERENCEは渡せないため、BY VALUE句は暗黙的で、省略可能です。

標準関数XMLExistsは、Oracle関数existsNodeと似ていますが、次の点で異なります。

  • XMLExistsは、任意のXQuery式を受け入れます(プロローグを含む可能性あり)。existsNodeは、XPath式のみ受け入れます(XPathは、XQueryの適切なサブセットです)。

  • XMLExistsは、XQuery式の引数が空でないシーケンスを戻すかどうかをテストします。existsNodeは、XPath式の引数が少なくとも1つの要素ノードまたはテキスト・ノードをターゲットとするかどうかをテストします。XPath式のセットは、XQuery式の適切なサブセットです。

  • XMLExistsはブール値TRUEまたはFALSEを戻します。existsNodeは、1または0を戻します。

existsNodeのかわりに、XMLExistsを使用することをお薦めします。

/PurchaseOrder/Referenceまたは/PurchaseOrder/Reference/text()などのXQuery式が、単一のノードをターゲットとする場合、XMLExistsはその式にtrueを戻します。どのノードも検索しないXQuery式を使用してXMLExistsをコールした場合、XMLExistsfalseを戻します。

関数XMLExistsは、問合せ内で使用できます。また、問合せの評価を高速化するためのファンクション索引を作成する場合にも使用できます。


注意:

Oracle XML DBは、XMLExistsの使用をSQLのWHERE句またはCASE式に制限します。XMLExistsSELECTリストの中で使用する必要がある場合は、次のようにそれをCASE式でラップします。
CASE WHEN XMLExists(...) THEN 'TRUE' ELSE 'FALSE' END

例4-2 XMLExistsを使用したノードの検索

この例では、SQL/XML標準関数XMLExistsを使用して、SpecialInstructionsExpediteに設定されている行を選択します。同じことを実行する際にOracle SQL関数existsNodeを使用する例4-3と比較してください。

SELECT OBJECT_VALUE
  FROM purchaseorder
  WHERE XMLExists('/PurchaseOrder[SpecialInstructions="Expedite"]'
                  PASSING OBJECT_VALUE);

OBJECT_VALUE
--------------------------------------------------------------------
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

13 rows selected.

SQL関数XMLExistsを使用してファンクション索引を作成すると、実行を高速化できます。また、XMLIndex索引を作成して、任意のXQuery検索を高速化することもできます。

EXISTSNODE SQL関数

図4-2に、SQL関数existsNodeの構文を示します。

図4-2 EXISTSNODEの構文

図4-2の説明が続きます
「図4-2 EXISTSNODEの構文」の説明

Oracle SQL関数existsNodeは、指定されたXPathパスが少なくとも1つのXML要素ノードまたはテキスト・ノードをターゲットとしているかどうかを調べます。参照している場合、この関数は1を戻します。参照していない場合は0(ゼロ)を戻します。パラメータXPath_stringに指定された名前空間接頭辞を対応する名前空間にマップするには、オプションのパラメータnamespace_stringを使用します。

Oracle関数existsNodeは、SQL/XML標準関数XMLExistsより前から存在しています。新規コードの中では、existsNodeのかわりに、XMLExistsを使用することをお薦めします。関数existsNodeは、次の点でXMLExistsと異なります。

  • XMLExistsは、任意のXQuery式を受け入れます(プロローグを含む可能性あり)。existsNodeは、XPath式のみ受け入れます(XPathは、XQueryの適切なサブセットです)。

  • XMLExistsは、XQuery式の引数が空でないシーケンスを戻すかどうかをテストします。existsNodeは、XPath式が少なくとも1つの要素ノードまたはテキスト・ノードをターゲットとするかどうかをテストします。

  • XMLExistsはXQueryブール値を戻します。existsNode1または0を戻します。

/PurchaseOrder/Referenceまたは/PurchaseOrder/Reference/text()のようなXPath式が、単一のノードをターゲットとする場合、existsNodeはその式に1を戻します。どのノードも検索しないXPath式を使用してexistsNodeをコールした場合、existsNode0を戻します。

関数existsNodeは、問合せ内で使用できます。また、問合せの評価を高速化するためのファンクション索引を作成する場合にも使用できます。


注意:

問合せにSQL関数existsNodeを使用する場合は、必ず、SELECTリストではなくWHERE句内で指定してください。

例4-3 EXISTSNODEを使用したノードの検索

この例では、SQL関数existsNodeを使用して、SpecialInstructionsExpediteに設定されている行を選択します。同じことを実行する際にSQL/XML標準関数XMLExistsを使用する例4-2と比較してください。

SELECT OBJECT_VALUE
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[SpecialInstructions="Expedite"]')
        = 1;

OBJECT_VALUE
----------------------------------------------------------------------------------
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

13 rows selected.

SQL関数existsNodeを使用してファンクション索引を作成すると、実行を高速化できます。また、XMLIndex索引を作成して、任意のXPath検索を高速化することもできます。

EXTRACT SQL関数

SQL関数extractは、existsNodeと似ています。ノード・セットをターゲットとするVARCHAR2 XPath文字列と、オプションのnamespaceパラメータを受け入れます。この関数は、XMLフラグメントを含むXMLTypeインスタンスを戻します。構文は、図4-3に示すとおりです。

extract(XMLType_instance IN XMLType,
        XPath_string IN VARCHAR2,
        namespace_string In VARCHAR2 := NULL) RETURN XMLType;

図4-3 EXTRACTの構文

図4-3の説明が続きます
「図4-3 EXTRACTの構文」の説明


注意:

extractのかわりに、SQL/XML関数XMLQueryを使用することもできます。Oracle特有の関数ではなく標準関数なので、通常はXMLQueryの使用をお薦めします。

extractXMLType値に適用すると、XPath式によって識別された文書からノードまたはノードの集合が抽出されます。XPath引数は、ノード・セットをターゲットにしている必要があります。したがって、たとえばXPath式/a/b/c[count('//d')=4]は使用できますが、count('//d')はスカラー値(数値)を戻すため、使用できません。

抽出されるノードは、要素、属性またはテキスト・ノードの場合があります。XPath式で複数のテキスト・ノードが参照されている場合、それらのテキスト・ノードは単一のテキスト・ノード値に縮小されます。namespaceを使用して、XPath式内の接頭辞の名前空間情報を指定できます。

extractから戻されるXMLTypeインスタンスは、整形式のXML文書である必要はありません。ノードのセットまたは単純なスカラー・データが含まれることもあります。スカラー・データを抽出するには、XMLTypeメソッドgetStringVal()およびgetNumberVal()を使用できます。

たとえば、XPath式/PurchaseOrder/Referenceは、前述のXML文書内のReference要素を識別します。一方、式/PurchaseOrder/Reference/text()は、このReference要素のテキスト・ノードを参照します。


注意:

テキスト・ノードはXMLTypeのインスタンスとみなされます。つまり、インスタンスにテキストのみが含まれる場合でも、次の式はXMLtypeインスタンスを戻します。
extract(OBJECT_VALUE, '/PurchaseOrder/Reference/text()')

メソッドgetStringVal()を使用すると、XMLTypeインスタンスからテキストをVARCHAR2値として取り出すことができます。


getStringVal()またはgetNumberVal()を使用してテキスト・ノードをSQLデータに変換する前に、text()ノード・テストを使用して、要素内のテキスト・ノードを識別します。text()ノード・テストを使用しない場合、XMLフラグメントが生成されます。

次に例を示します。

  • XPath /PurchaseOrder/Referenceは、フラグメント<Reference> ... </Reference>を識別します。

  • XPath /PurchaseOrder/Reference/text()は、Reference要素のテキスト・ノードの値を識別します。

XML文書内で要素が繰り返されている場合、XPath位置述語(索引とも呼ばれる)を使用して、個々の要素を識別できます。例4-4に示すようなXML文書の場合は、次の式を使用できます。

  • 最初のLineItem要素を識別するXPath式//LineItem[1]

  • 2番目のLineItem要素を識別するLineItem[2]

例4-4 発注書のXML文書

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

SQL関数extractの結果は、常にXMLTypeインスタンスになります。XPathパスの適用によって空のセットが生成される場合、extractNULL値を戻します。

SQL関数extractは、多くの場合に使用できます。この関数を使用すると、次のものを抽出できます。

  • 処理を高速化するためのファンクション索引を作成可能にする数値

  • SQL文のFROM句で使用するコレクション式

  • 後で集計して別の文書を作成するためのフラグメント

例4-5 EXTRACTを使用したノード値の抽出

この例では、SQL関数extractを使用して、SpecialInstructions属性の値がExpediteであるPurchaseOrderノードの子Referenceを取り出します。

SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Reference') "REFERENCE"
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[SpecialInstructions="Expedite"]')
        = 1;

REFERENCE
------------------------------------------------------------
<Reference>AMCEWEN-20021009123336271PDT</Reference>
<Reference>SKING-20021009123336321PDT</Reference>
<Reference>AWALSH-20021009123337303PDT</Reference>
<Reference>JCHEN-20021009123337123PDT</Reference>
<Reference>AWALSH-20021009123336642PDT</Reference>
<Reference>SKING-20021009123336622PDT</Reference>
<Reference>SKING-20021009123336822PDT</Reference>
<Reference>AWALSH-20021009123336101PDT</Reference>
<Reference>WSMITH-20021009123336412PDT</Reference>
<Reference>AWALSH-20021009123337954PDT</Reference>
<Reference>SKING-20021009123338294PDT</Reference>
<Reference>WSMITH-20021009123338154PDT</Reference>
<Reference>TFOX-20021009123337463PDT</Reference>

13 rows selected.

注意:

SQL関数extractValueXMLTypeメソッドgetStringVal()では、エンティティのエンコーディングの処理方法が異なります。関数extractValueはエンコードされたエンティティをエスケープしませんが、メソッドgetStringVal()はエンティティのエンコーディングを完全な状態で保持したデータを戻します。

XMLCAST SQL関数

図4-4に、SQL/XMLの標準関数XMLCastの構文を示します。

図4-4 XMLCastの構文

図4-4の説明が続きます
「図4-4 XMLCastの構文」の説明

SQL/XML標準関数XMLCastは、その最初の引数を2番目の引数で指定されるSQLスカラー・データ型にキャストします。最初の引数は、評価されるSQL式です。データ型NUMBERVARCHAR2、および任意の日時データ型を2番目の引数として使用できます。


注意:

SQL/XML標準とは異なり、Oracle XML DBはXMLCastの使用を制限し、XMLをSQLスカラー・データ型にキャストします。XMLのXMLへのキャスト、またはSQLスカラー・データ型からXMLへのキャストはサポートされません。

最初のXMLCast引数の評価結果は、XML値となります。この値は、XQueryアトム化プロセスを使用して、XQueryアトム値をターゲットのデータ型にキャストすることにより、ターゲットのSQLデータ型に変換されます。この変換が失敗すると、エラーが発生します。変換が成功すると、戻される結果は、ターゲットのデータ型のインスタンスとなります。

標準関数XMLCastは、Oracle関数extractValueと似ていますが、extractValueがターゲットのデータ型の指定を許可しない、または指定を必要とする点で異なります。この点では、extractValueのほうが便利な場合があります。XMLCastを使用すると、移植性に加えてデータ型を制御できます。SQLスカラー・データ型がコンパイル時に決まらない場合、extractValueは、時間の値VARCHAR2(4000)を戻しますが、これは予期または希望した結果とは異なる場合があります。SQL関数castを使用してこの問題を回避できますが、この場合は、XMLCastを選択することをお薦めします。

例4-6 XMLCASTを使用したXMLフラグメントのスカラー値の抽出

この問合せは、Referenceノードのスカラー値を抽出します。同じことを実行する際にOracle SQL関数extractValueを使用する例4-7と比較してください。このノードのスカラー値の抽出は、関数extractを使用して<Reference>ノードそのものを取り出す例4-5とは対照的です。

SELECT XMLCast(XMLQuery('/PurchaseOrder/Reference' PASSING OBJECT_VALUE
                                                   RETURNING CONTENT)
               AS VARCHAR2(100)) "REFERENCE"
  FROM purchaseorder
  WHERE XMLExists('/PurchaseOrder[SpecialInstructions="Expedite"]'
                  PASSING OBJECT_VALUE);

REFERENCE
----------------------------
AMCEWEN-20021009123336271PDT
SKING-20021009123336321PDT
AWALSH-20021009123337303PDT
JCHEN-20021009123337123PDT
AWALSH-20021009123336642PDT
SKING-20021009123336622PDT
SKING-20021009123336822PDT
AWALSH-20021009123336101PDT
WSMITH-20021009123336412PDT
AWALSH-20021009123337954PDT
SKING-20021009123338294PDT
WSMITH-20021009123338154PDT
TFOX-20021009123337463PDT

13 rows selected.

SQL関数existsNodeを使用してファンクション索引を作成すると、実行を高速化できます。また、XMLIndex索引を作成して、任意のXPath検索を高速化することもできます。

EXTRACTVALUE SQL関数

SQL関数extractValueは、XMLTypeインスタンスと、ノード・セットをターゲットとするXPath式をパラメータとして取ります。この関数は、XMLTypeインスタンスのXPath評価の結果に対応するSQLスカラー値を戻します。

  • XML Schemaに基づく文書: XML Schemaに基づく文書では、Oracle Databaseが戻り値の型を推測できる場合、該当する型のスカラー値が戻されます。それ以外の場合、結果はVARCHAR2型です。

  • スキーマに基づかない文書: 問合せがSQL/XMLビューにある場合など、extractValueがリライトされる可能性がある場合は、該当する型のスカラー値が戻されます。それ以外の場合、結果はVARCHAR2型です。

図4-5に、extractValueの構文を示します。

図4-5 EXTRACTVALUEの構文

図4-5の説明が続きます
「図4-5 EXTRACTVALUEの構文」の説明

SQL関数extractValueは、文書に関連付けられたXML Schemaや、SQL/XMLビューなどの他の情報から、正しい戻り型を判断しようとします。正しい戻り型が判断できない場合、Oracle XML DBはVARCHAR2を戻します。XML Schemaに基づくコンテンツでは、extractValueは多くの場合、基礎となるデータ型を戻します。CLOB値は直接戻されます。

特定のデータ型が必要な場合は、extractValueまたはextract.getStringVal()の結果に対してto_charto_dateなどの変換関数を適用できます。これは、問合せがリライト可能かどうかに関係なく、複数の異なる問合せ間で一貫性を保持するために役立ちます。

EXTRACTVALUEの便利な使用

SQL関数extractValueは便利な関数であり、extractよりも簡単に必要な値を抽出できます。この関数は、extract().getStringVal()またはextract().getnumberval()のかわりに使用できます。

たとえば、extract(x, 'path/text()').getStringVal()のかわりにextractValue(x, 'path/text()')を使用できます。pathのノードに子が1つしかなく、かつその子がテキスト・ノードの場合、XPath引数でtext()テストを使用しなくてもかまいません(extractValue(x, 'path'))。それ以外の場合は、text()を使用しないとエラーが発生します。

SQL関数extractValueの構文は、関数extractの構文と同じです。

EXTRACTVALUEの特性

SQL関数extractValueには、次のような特性があります。

  • スカラー値(NUMBERVARCHAR2など)のみを戻します。XMLノードまたは複合的なコンテンツを戻すことはできません。extractValueがスカラー値を戻すことができない場合、エラーが発生します。

  • デフォルトでは、extractValueはVARCHAR2値を戻します。長さが4Kを超える場合、ランタイム・エラーが発生します。

  • 問合せのコンパイル時にXML Schema情報が使用可能な場合、そのXML Schema情報に基づいて、戻される値のデータ型が決まります。たとえば、XPath /PurchaseOrder/LineItems/LineItem[1]/Part/@QuantityのXML Schema情報に数値が指定されている場合、extractValueNUMBERを戻します。

  • extractValueがSQL/XMLビューに適用され、コンパイル時にビュー定義から列のデータ型を判断できる場合は、該当する型が戻ります。

  • XPath引数がノードを指定している場合、そのノードは1つの子テキストを持つ必要があります(そうでない場合、エラーが発生します)。その子テキストが戻されます。たとえば、次の式はReferenceノードの子テキストを抽出します。

    extractValue(xmlinstance, '/PurchaseOrder/Reference')
    
    
  • XPath引数は、ノード・セットをターゲットにしている必要があります。したがって、たとえばXPath式/a/b/c[count('//d')=4]は使用できますが、count('//d')はスカラー値(数値)を戻すため、使用できません。

例4-7 EXTRACTVALUEを使用したXMLフラグメントのスカラー値の抽出

この問合せは、Referenceノードのスカラー値を抽出します。同じことを実行する際にSQL/XML標準関数XMLCastを使用する例4-6と比較してください。

SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference') "REFERENCE"
  FROM purchaseorder
  WHERE XMLExists('/PurchaseOrder[SpecialInstructions="Expedite"]'
                  PASSING OBJECT_VALUE);

REFERENCE
----------------------------
AMCEWEN-20021009123336271PDT
SKING-20021009123336321PDT
AWALSH-20021009123337303PDT
JCHEN-20021009123337123PDT
AWALSH-20021009123336642PDT
SKING-20021009123336622PDT
SKING-20021009123336822PDT
AWALSH-20021009123336101PDT
WSMITH-20021009123336412PDT
AWALSH-20021009123337954PDT
SKING-20021009123338294PDT
WSMITH-20021009123338154PDT
TFOX-20021009123337463PDT

13 rows selected.

注意:

関数extractValueXMLTypeメソッドgetStringVal()では、エンティティのエンコーディングの処理方法が異なります。関数extractValueはエンコードされたエンティティをエスケープしませんが、メソッドgetStringVal()はエンティティのエンコーディングを完全な状態で保持したデータを戻します。

EXTRACTVALUE XPath式は単一のリーフ・ノードに一致する必要がある

例4-8は、SQL関数extractValueの不適切な使用方法をいくつか示しています。最初の問合せでは、XPath式がリーフ・ノード(テキスト・ノードや属性値)ではなく親ノードを識別しています。2番目の問合せでは、XPath式は文書内の3つのノードと一致しています(XPath式は1つのノードのみと一致する必要があります)。2番目の問合せに対してどのエラーが発生するかは、XPathのリライトが行われるかどうかによって決まります。

例4-8 EXTRACTVALUEの無効な使用

SELECT extractValue(OBJECT_VALUE,'/PurchaseOrder/LineItems/LineItem[1]')
  FROM purchaseorder;
  FROM purchaseorder
     *
ERROR at line 3:
ORA-19026: EXTRACTVALUE can only retrieve value of leaf node


SELECT extractValue(OBJECT_VALUE,
                    '/PurchaseOrder/LineItems/LineItem/Description')
  FROM purchaseorder;
SELECT extractValue(OBJECT_VALUE,
                    '/PurchaseOrder/LineItems/LineItem/Description')
 *
ERROR at line 1:
ORA-01427: single-row subquery returns more than one row

XPathのリライトが行われない場合、この問合せでは次のエラーが発生する可能性があります。

ORA-19025: EXTRACTVALUE returns value of only one node

SQLを使用したXMLデータの問合せ

次の各例で、SQLを使用してXMLデータを問い合せる方法を示します。

例4-9 EXTRACTVALUEおよびEXISTSNODEを使用したXMLTypeの問合せ

この例では、purchaseorder表に2行を挿入してから、extractValueを使用してそれらの行のデータを問い合せます。

INSERT INTO purchaseorder
  VALUES (XMLType(bfilename('XMLDIR', 'SMCCAIN-2002091213000000PDT.xml'),
                  nls_charset_id('AL32UTF8')));

1 row created.

INSERT INTO purchaseorder
  VALUES (XMLType(bfilename('XMLDIR', 'VJONES-20020916140000000PDT.xml'),
                  nls_charset_id('AL32UTF8')));

1 row created.

SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference') REFERENCE,
       extractValue(OBJECT_VALUE, '/PurchaseOrder/*//User') USERID,
       CASE
         WHEN existsNode(OBJECT_VALUE, '/PurchaseOrder/Reject/Date') = 1
           THEN 'Rejected'
           ELSE 'Accepted'
       END "STATUS",
       extractValue(OBJECT_VALUE, '//Date') STATUS_DATE
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE,'//Date') = 1
  ORDER BY extractValue(OBJECT_VALUE,'//Date');

REFERENCE                        USERID   STATUS   STATUS_DATE
-------------------------------- -------- -------- ------------
VJONES-20020916140000000PDT      SVOLLMAN Accepted 2002-10-11
SMCCAIN-2002091213000000PDT      SKING    Rejected 2002-10-12

2 rows selected.

例4-10 一時XMLTypeデータの問合せ

この例では、PL/SQLカーソルを使用してXMLデータを問い合せます。ローカルのXMLTypeインスタンスは、一時データを格納するために使用されます。

DECLARE
  xNode          XMLType;
  vText          VARCHAR2(256);
  vReference     VARCHAR2(32);
  CURSOR getPurchaseOrder(reference IN VARCHAR2) IS
           SELECT OBJECT_VALUE XML
             FROM purchaseorder
             WHERE existsNode(OBJECT_VALUE,
                              '/PurchaseOrder[Reference="'|| reference || '"]')
                   = 1;
BEGIN
  vReference := 'EABEL-20021009123335791PDT';
  FOR c IN getPurchaseOrder(vReference) LOOP
    xNode := c.XML.extract('//Requestor');
    vText := xNode.extract('//text()').getStringVal();
    DBMS_OUTPUT.put_line('The Requestor for Reference '
                         || vReference || ' is '|| vText);
  END LOOP;
  vReference := 'PTUCKER-20021009123335430PDT';
  FOR c IN getPurchaseOrder(vReference) LOOP
    xNode := c.XML.extract('//LineItem[@ItemNumber="1"]/Description');
    vText := xNode.extract('//text()').getStringVal();
    DBMS_OUTPUT.put_line('The Description of LineItem[1] for Reference '
                         || vReference || ' is '|| vText);
  END LOOP;
END;/
The Requestor for Reference EABEL-20021009123335791PDT is Ellen S. Abel
The Description of LineItem[1] for Reference PTUCKER-20021009123335430PDT is Picnic at Hanging Rock

PL/SQL procedure successfully completed.

例4-11 XMLTableを使用したXMLデータの抽出およびデータベース表への挿入

この例では、SQL関数XMLTableを使用して、XML発注書からデータを抽出し、そのデータをデータベース表に挿入します。

CREATE TABLE purchaseorder_table (reference           VARCHAR2(28) PRIMARY KEY,
                                  requestor           VARCHAR2(48),
                                  actions             XMLType,
                                  userid              VARCHAR2(32),
                                  costcenter          VARCHAR2(3),
                                  shiptoname          VARCHAR2(48),
                                  address             VARCHAR2(512),
                                  phone               VARCHAR2(32),
                                  rejectedby          VARCHAR2(32),
                                  daterejected        DATE,
                                  comments            VARCHAR2(2048),
                                  specialinstructions VARCHAR2(2048));

CREATE TABLE purchaseorder_lineitem (reference,
                                     FOREIGN KEY ("REFERENCE")
                                       REFERENCES "PURCHASEORDER_TABLE" ("REFERENCE") ON DELETE CASCADE,
                                     lineno      NUMBER(10), PRIMARY KEY ("REFERENCE", "LINENO"),
                                     upc         VARCHAR2(14),
                                     description VARCHAR2(128),
                                     quantity    NUMBER(10),
                                     unitprice   NUMBER(12,2));

INSERT INTO purchaseorder_table (reference, requestor, actions, userid, costcenter, shiptoname, address,
                                 phone, rejectedby, daterejected, comments, specialinstructions)
  SELECT t.reference, t.requestor, t.actions, t.userid, t.costcenter, t.shiptoname, t.address,
          t.phone, t.rejectedby, t.daterejected, t.comments, t.specialinstructions
    FROM purchaseorder p,
         XMLTable('/PurchaseOrder' PASSING p.OBJECT_VALUE
                  COLUMNS reference           VARCHAR2(28)   PATH 'Reference',
                          requestor           VARCHAR2(48)   PATH 'Requestor',
                          actions             XMLType        PATH 'Actions',
                          userid              VARCHAR2(32)   PATH 'User',
                          costcenter          VARCHAR2(3)    PATH 'CostCenter',
                          shiptoname          VARCHAR2(48)   PATH 'ShippingInstructions/name',
                          address             VARCHAR2(512)  PATH 'ShippingInstructions/address',
                          phone               VARCHAR2(32)   PATH 'ShippingInstructions/telephone',
                          rejectedby          VARCHAR2(32)   PATH 'Rejection/User',
                          daterejected        DATE           PATH 'Rejection/Date',
                          comments            VARCHAR2(2048) PATH 'Rejection/Comments',
                          specialinstructions VARCHAR2(2048) PATH 'SpecialInstructions') t
    WHERE t.reference = 'EABEL-20021009123336251PDT';

1 row created.

INSERT INTO purchaseorder_lineitem (reference, lineno, upc, description, quantity, unitprice)
  SELECT t.reference, li.lineno, li.upc, li.description, li.quantity, li.unitprice
    FROM purchaseorder p,
         XMLTable('/PurchaseOrder' PASSING p.OBJECT_VALUE
                  COLUMNS reference VARCHAR2(28) PATH 'Reference',
                          lineitem XMLType PATH 'LineItems/LineItem') t,
         XMLTable('LineItem' PASSING t.lineitem
                  COLUMNS lineno      NUMBER(10)    PATH '@ItemNumber',
                          upc         VARCHAR2(14)  PATH 'Part/@Id',
                          description VARCHAR2(128) PATH 'Description',
                          quantity    NUMBER(10)    PATH 'Part/@Quantity',
                          unitprice   NUMBER(12,2)  PATH 'Part/@UnitPrice') li
    WHERE t.reference = 'EABEL-20021009123336251PDT';

3 rows created.

SELECT reference, userid, shiptoname, specialinstructions FROM purchaseorder_table;

REFERENCE                        USERID   SHIPTONAME                                       SPECIALINSTRUCTIONS
-------------------------------- -------- ------------------------------------------------ -------------------
EABEL-20021009123336251PDT       EABEL    Ellen S. Abel                                    Counter to Counter

1 row selected.

SELECT reference, lineno, upc, description, quantity FROM purchaseorder_lineitem;

REFERENCE                            LINENO UPC            DESCRIPTION                          QUANTITY
-------------------------------- ---------- -------------- ---------------------------------- ----------
EABEL-20021009123336251PDT                1 37429125526    Samurai 2: Duel at Ichijoji Temple          3
EABEL-20021009123336251PDT                2 37429128220    The Red Shoes                               4
EABEL-20021009123336251PDT                3 715515009058   A Night to Remember                         1

3 rows selected.

例4-12 EXTRACTVALUEを使用したXMLデータの抽出および表への挿入

この例では、SQL関数extractValueを使用して、XML発注書からデータを抽出し、そのデータをSQLリレーショナル表に挿入します。

CREATE OR REPLACE PROCEDURE insertPurchaseOrder(purchaseorder XMLType) AS reference VARCHAR2(28);
BEGIN
  INSERT INTO purchaseorder_table (reference, requestor, actions, userid, costcenter, shiptoname, address,
                                   phone, rejectedby, daterejected, comments, specialinstructions)
    VALUES (extractValue(purchaseorder, '/PurchaseOrder/Reference'),
            extractValue(purchaseorder, '/PurchaseOrder/Requestor'),
            extract(purchaseorder,      '/PurchaseOrder/Actions'),
            extractValue(purchaseorder, '/PurchaseOrder/User'),
            extractValue(purchaseorder, '/PurchaseOrder/CostCenter'),
            extractValue(purchaseorder, '/PurchaseOrder/ShippingInstructions/name'),
            extractValue(purchaseorder, '/PurchaseOrder/ShippingInstructions/address'),
            extractValue(purchaseorder, '/PurchaseOrder/ShippingInstructions/telephone'),
            extractValue(purchaseorder, '/PurchaseOrder/Rejection/User'),
            extractValue(purchaseorder, '/PurchaseOrder/Rejection/Date'),
            extractValue(purchaseorder, '/PurchaseOrder/Rejection/Comments'),
            extractValue(purchaseorder, '/PurchaseOrder/SpecialInstructions'))
    RETURNING reference INTO reference;

  INSERT INTO purchaseorder_lineitem (reference, lineno, upc, description, quantity, unitprice)
    SELECT reference, li.lineno, li.upc, li.description, li.quantity, li.unitprice
      FROM XMLTable('/PurchaseOrder/LineItems/LineItem' PASSING purchaseorder
                    COLUMNS lineno      NUMBER(10)    PATH '@ItemNumber',
                            upc         VARCHAR2(14)  PATH 'Part/@Id',
                            description VARCHAR2(128) PATH 'Description',
                            quantity    NUMBER(10)    PATH 'Part/@Quantity',
                            unitprice   NUMBER(12,2)  PATH 'Part/@UnitPrice') li;
END;/
Procedure created.
CALL insertPurchaseOrder(XMLType(bfilename('XMLDIR', 'purchaseOrder.xml'), nls_charset_id('AL32UTF8')));

Call completed.
SELECT reference, userid, shiptoname, specialinstructions FROM purchaseorder_table;

REFERENCE                        USERID   SHIPTONAME                                       SPECIALINSTRUCTIONS
-------------------------------- -------- ------------------------------------------------ -------------------
SBELL-2002100912333601PDT        SBELL    Sarah J. Bell                                    Air Mail

1 row selected.

SELECT reference, lineno, upc, description, quantity FROM purchaseorder_lineitem;

REFERENCE                 LINENO UPC          DESCRIPTION                        QUANTITY
------------------------- ------ ------------ ---------------------------------- --------
SBELL-2002100912333601PDT      1 715515009058 A Night to Remember                       2
SBELL-2002100912333601PDT      2 37429140222  The Unbearable Lightness Of Being         2
SBELL-2002100912333601PDT      3 715515011020 Sisters                                   4

3 rows selected.

例4-13 XMLTypeメソッドextract()およびexistsNode()を使用したXMLデータの検索

この例では、顧客名に"ll"(Lが2個)が付き、出荷指示に"Shores"という語が含まれている発注書の要素PurchaseOrderから発注書名を抽出します。SQL関数extractおよびexistsNodeではなく、XMLTypeメソッドextract()およびexistsNode()を使用しています。

SELECT p.OBJECT_VALUE.extract('/PurchaseOrder/Requestor/text()').getStringVal() NAME,
       count(*)
  FROM purchaseorder p
  WHERE p.OBJECT_VALUE.existsNode
          ('/PurchaseOrder/ShippingInstructions[ora:contains(address/text(),"Shores")>0]',
           'xmlns:ora="http://xmlns.oracle.com/xdb"') = 1
    AND p.OBJECT_VALUE.extract('/PurchaseOrder/Requestor/text()').getStringVal() LIKE '%ll%'
  GROUP BY p.OBJECT_VALUE.extract('/PurchaseOrder/Requestor/text()').getStringVal();

NAME                   COUNT(*)
-------------------- ----------
Allan D. McEwen               9
Ellen S. Abel                 4
Sarah J. Bell                13
William M. Smith              7

4 rows selected.

例4-14 EXTRACTVALUEを使用したXMLデータの検索

この例は、例4-13の問合せが、SQL関数extractValueを使用するようにリライトされたものです。

SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Requestor') NAME, count(*)
  FROM purchaseorder
  WHERE existsNode
          (OBJECT_VALUE,
           '/PurchaseOrder/ShippingInstructions[ora:contains(address/text(), "Shores")>0]',
           'xmlns:ora="http://xmlns.oracle.com/xdb') = 1
    AND extractValue(OBJECT_VALUE, '/PurchaseOrder/Requestor/text()') LIKE '%ll%'
  GROUP BY extractValue(OBJECT_VALUE, '/PurchaseOrder/Requestor');

NAME                   COUNT(*)
-------------------- ----------
Allan D. McEwen               9
Ellen S. Abel                 4
Sarah J. Bell                13
William M. Smith              7

4 rows selected.

例4-15は、SQL関数extractを使用して、XPath式によって識別されるノードを抽出する方法を示しています。extractにより、XMLフラグメントを含むXMLTypeインスタンスが戻されます。検索結果は、ノードの集合、単一のノードまたはテキスト値のいずれかになります。XMLTypeインスタンスにisFragment()メソッドを使用すると、結果がフラグメントかどうかを判断できます。


注意:

フラグメントはXMLType列に挿入できません。SQL関数sys_XMLGenを使用すると、囲みタグを追加することによってフラグメントを整形式の文書に変換できます。「SQL関数SYS_XMLGENを使用したXMLの生成」を参照してください。ただし、様々なXMLType関数を使用して、フラグメントに追加の問合せを実行できます。

例4-15 EXTRACTを使用したXMLTypeインスタンスからのフラグメントの抽出

SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference') REFERENCE, count(*)
  FROM purchaseorder, XMLTable('//LineItem[Part/@Id="37429148327"]' PASSING OBJECT_VALUE)
  WHERE extract(OBJECT_VALUE, '/PurchaseOrder/LineItems/LineItem[Part/@Id="37429148327"]').isFragment() = 1
  GROUP BY extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference')
  ORDER BY extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference');

REFERENCE                          COUNT(*)
-------------------------------- ----------
AWALSH-20021009123337303PDT               1
AWALSH-20021009123337954PDT               1
DAUSTIN-20021009123337553PDT              1
DAUSTIN-20021009123337613PDT              1
LSMITH-2002100912333722PDT                1
LSMITH-20021009123337323PDT               1
PTUCKER-20021009123336291PDT              1
SBELL-20021009123335771PDT                1
SKING-20021009123335560PDT                1
SMCCAIN-20021009123336151PDT              1
SMCCAIN-20021009123336842PDT              1
SMCCAIN-2002100912333894PDT               1
TFOX-2002100912333681PDT                  1
TFOX-20021009123337784PDT                 3
WSMITH-20021009123335650PDT               1
WSMITH-20021009123336412PDT               1

16 rows selected.

XMLインスタンスおよび表内のXMLデータの更新

この項では、一時XMLインスタンスおよび表に格納されたXMLデータの更新について説明します。次のSQL関数の使用方法を詳しく説明します。

XML文書全体の更新

未構造化記憶域(CLOB)では、更新を行うと文書全体が効果的に置換されます。XML文書全体を更新するには、SQLのUPDATE文を使用します。UPDATE文のSET句の右側にはXMLTypeインスタンスを指定する必要があります。これを作成するには、次のいずれかの方法を使用します。

  • XMLインスタンスを戻すSQL関数またはXMLコンストラクタを使用する方法

  • 既存のXMLインスタンスを変更およびバインドするPL/SQL DOM APIs for XMLTypeを使用する方法

  • 既存のXMLインスタンスを変更およびバインドするJava PL/SQL DOM APIを使用する方法

CLOB値(未構造化記憶域)として格納されているXML Schemaに基づかないXML文書を更新する場合は、常にXML文書全体が更新されます。バイナリXMLとして格納されているXML Schemaに基づかないXML文書は、ピース単位で更新できます。「XML Schemaに基づくXML文書および基づかないXML文書の更新」を参照してください。

例4-16 UPDATE SQL文を使用したXMLTypeの更新

この例では、SQL UPDATE文を使用してXMLTypeインスタンスを更新します。

SELECT t.reference, li.lineno, li.description
  FROM purchaseorder p,
       XMLTable('/PurchaseOrder' PASSING p.OBJECT_VALUE
                COLUMNS reference VARCHAR2(28) PATH 'Reference',
                        lineitem  XMLType      PATH 'LineItems/LineItem') t
       XMLTable('/LineItem' PASSING t.lineitem
                COLUMNS lineno      NUMBER(10)    PATH '@ItemNumber',
                        description VARCHAR2(128) PATH 'Description') li
  WHERE t.reference = 'DAUSTIN-20021009123335811PDT' AND ROWNUM < 6;

REFERENCE                         LINENO DESCRIPTION
-------------------------------- ------- -----------------
DAUSTIN-20021009123335811PDT           1 Nights of Cabiria
DAUSTIN-20021009123335811PDT           2 For All Mankind
DAUSTIN-20021009123335811PDT           3 Dead Ringers
DAUSTIN-20021009123335811PDT           4 Hearts and Minds
DAUSTIN-20021009123335811PDT           5 Rushmore

5 rows selected.

UPDATE purchaseorder
  SET OBJECT_VALUE = XMLType(bfilename('XMLDIR', 'NEW-DAUSTIN-20021009123335811PDT.xml'),
                             nls_charset_id('AL32UTF8'))
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="DAUSTIN-20021009123335811PDT"]') = 1;

1 row updated.

SELECT t.reference, li.lineno, li.description
  FROM purchaseorder p,
       XMLTable('/PurchaseOrder' PASSING p.OBJECT_VALUE
                COLUMNS reference VARCHAR2(28) PATH 'Reference',
                        lineitem  XMLType      PATH 'LineItems/LineItem') t
       XMLTable('/LineItem' PASSING t.lineitem
                COLUMNS lineno      NUMBER(10)    PATH '@ItemNumber',
                        description VARCHAR2(128) PATH 'Description') li
  WHERE t.reference = 'DAUSTIN-20021009123335811PDT';

REFERENCE                         LINENO DESCRIPTION
-------------------------------- ------- --------------------------------
DAUSTIN-20021009123335811PDT           1 Dead Ringers
DAUSTIN-20021009123335811PDT           2 Getrud
DAUSTIN-20021009123335811PDT           3 Branded to Kill

3 rows selected.

XMLデータを更新するためのSQL関数

XMLデータを付加的に更新する(周囲のXML文書全部を置き換えずにXMLデータを置換、挿入または削除する)ために使用できるSQL関数がいくつかあります。これは、部分更新とも呼ばれます。これらのSQL関数については、次の各項で説明します。

  • updateXML: 任意の種類のXMLノードを置換します。「UPDATEXML SQL関数」を参照してください。

  • insertChildXML: XMLの要素ノードまたは属性ノードを、指定された要素ノードの子として挿入します。「INSERTCHILDXML SQL関数」を参照してください。

  • insertChildXMLbefore: 新しいコレクション要素を、同じ型の指定されたコレクション要素の直前に挿入します。「INSERTCHILDXMLBEFORE SQL関数」を参照してください。

  • insertChildXMLafter: 新しいコレクション要素を、同じ型の指定されたコレクション要素の直後に挿入します。「INSERTCHILDXMLAFTER SQL関数」を参照してください。

  • insertXMLbefore: 任意の種類のXMLノードを、指定されたノード(属性ノード以外)の直前に挿入します。「INSERTXMLBEFORE SQL関数」を参照してください。

  • insertXMLafter: 任意の種類のXMLノードを、指定されたノード(属性ノード以外)の直後に挿入します。「INSERTXMLAFTER SQL関数」を参照してください。

  • appendChildXML: 任意の種類のXMLノードを、指定された要素ノードの最後の子ノードとして挿入します。「APPENDCHILDXML SQL関数」を参照してください。

  • deleteXML: 任意の種類のXMLノードを削除します。「DELETEXML SQL関数」を参照してください。

XMLデータを挿入するには、関数insertChildXMLinsertXMLbeforeinsertChildXMLafterinsertXMLbeforeinsertXMLafterおよびappendChildXMLを使用します。XMLデータを削除するには、deleteXMLを使用します。XMLデータを置換するには、updateXMLを使用します。

特に、親ノード全体を置き換えることによってXMLデータを挿入または削除する場合は、関数updateXMLを使用しないでください。使用しても機能しますが、これ以外のいずれかの関数を使用するほうがローカルな更新を実行できるため、効率的です。

これらの関数は、それ自体ではデータベースのデータを変更しません。これらは、副次的な影響のない純粋な関数です。これらの各関数は、入力されたXMLデータにXPath式の引数を適用し、入力されたXMLデータの変更済コピーを戻します。その後、その結果を使用してSQL DML演算子UPDATEを実行し、データベース・データを更新できます。これは、SQL関数upperを使用してデータベースのデータを大文字に変換する方法と変わりません。UPDATEのようなSQL DML演算子を使用して格納されたデータを変更する必要があります。

これらの関数はそれぞれ、XML Schemaに基づくXML文書に対しても、XML Schemaに基づかないXML文書に対しても使用できます。XML Schemaに基づくXML文書の場合、これらのSQL関数は結果に対して部分検証を実行します。該当する場合は、引数の値がXML Schemaと互換しているかどうかも確認されます。


注意:

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

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



関連項目:

XML Schemaに対する部分検証の詳細は、「部分検証」を参照してください。

SQL関数を使用したXML要素の挿入

XMLノードを既存のXMLデータ(のコピー)に挿入するためのSQL関数がいくつかあります。いずれも、XPath式により参照されるノードを複数の場所に挿入できます。各関数は、新しいノードの挿入位置と、ターゲットXMLデータの参照方法が異なります。

  • 関数appendChildXMLは、ターゲット要素にノードを追加します。つまり、ターゲット要素ごとに、任意の種類の1つ以上のノードを要素の最後の子として挿入します。

  • 関数insertChildXMLは、ターゲット要素の下に新しい子(同じ型の1つ以上の要素、または単一の属性)を挿入します。親の下の新しい子要素の位置は指定されません。ターゲット・データがXML Schemaに基づいている場合、そのスキーマを使用して挿入位置を指定できる場合もあります。できない場合、挿入位置は任意です。

  • 関数insertXMLbeforeは、任意の種類の1つ以上のノードを、(属性ノード以外の)ターゲット・ノードの直前に挿入します。

    関数insertXMLafterも同様にノードを挿入しますが、ターゲットの直前ではなく直後に挿入します。

  • 関数insertChildXMLbeforeinsertChildXMLと似ていますが、挿入されるノードが(属性でなく)要素である必要があることと、兄弟関係における新しい要素の位置をユーザーが指定する点が異なります。また、insertXMLbeforeと似ていますが、任意の要素ではなくコレクション要素のみを挿入する点が異なります。挿入位置により、後続のコレクション・メンバーが指定されます。挿入する実際の要素は、コレクションの要素型に対応している必要があります。

    関数insertChildXMLafterも同様にノードを挿入しますが、ターゲットの直前ではなく直後に挿入します。

insertChildXMLbeforeinsertChildXMLafter)とinsertXMLbeforeinsertXMLbeforeafter)は結果は似ていますが、ターゲットの場所の表現方法が異なります。前者の関数では、ターゲットは新しい子の親です。後者の関数では、ターゲットは後ろの(または前の)兄弟です。この違いは、関数名(Child)に表れています。

たとえば、新しいLineItem要素を、/PurchaseOrder/LineItems要素の3つ下にあるLineItem要素の前に挿入する場合、insertChildXMLbeforeを使用し、ターゲットの親を/PurchaseOrder/LineItemsとして指定し、後続の兄弟をLineItem[3]として指定します。または、insertXMLbeforeを使用し、ターゲットの後続の兄弟を/PurchaseOrder/LineItems/LineItem[3]として指定することもできます。insertChildXMLを使用して挿入する場合は、コレクション内の新しい要素の位置を指定できません。結果の位置は不確定です。

さらに、これらの関数のうち、insertXMLbeforeinsertXMLafterおよびappendChildXML以外はすべて、オブジェクト・リレーショナル形式またはバイナリXMLとして格納されているXMLType表および列に対するSQL UPDATE操作のために最適化されます。

UPDATEXML SQL関数

SQL関数updateXMLは、任意の種類のXMLノードを置換します。更新のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。

入力されたXMLTypeインスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。

関数updateXMLには、次のパラメータがあります(この順序どおり)。

  • target-dataXMLType): 置換するターゲット・ノードを含むXMLデータ。

  • 1つ以上の、xpathパラメータとreplacementパラメータの組。

    • xpathVARCHAR2): 置換するtarget-data内のノードを検索するXPath 1.0式。ターゲットのノードはそれぞれ、replacementで置換されます。これらは、どのような種類のノードでもかまいません。xpathがノードの空シーケンスと一致する場合、置換は行われません。target-dataがそのままの状態で戻されます(エラーは発生しません)。

    • replacementXMLTypeまたはVARCHAR2): xpathでターゲットとなっているデータを置換するXMLデータ。replacementのデータ型は、置換されるデータと一致している必要があります。xpathの置換のターゲットが要素ノードの場合、データ型はXMLTypeである必要があります。xpathのターゲットが属性ノードまたはテキスト・ノードの場合、データ型はVARCHAR2である必要があります。属性ノードの場合、replacementは、名前を含む完全な属性ノード(たとえば、my_attribute="23")ではなく、属性の置換値のみ(たとえば、23)です。

  • namespaceVARCHAR2、オプション): パラメータxpathのXML名前空間。

SQL関数updateXMLを使用すると、既存の要素、属性およびその他のノードを新しい値で置換できます。この方法は、新しいノードを挿入したり、既存のノードを削除する方法として効率的ではありません。挿入および更新は、updateXMLを使用して、挿入または削除されるノードの親であるノード全部を置換することによってのみ実行できます。

関数updateXMLは、メモリー内の一時XMLインスタンスのみを更新します。表に格納されたデータを更新するには、SQLのUPDATE文を使用します。

図4-6に構文を示します。

図4-6 UPDATEXMLの構文

図4-6の説明が続きます
「図4-6 UPDATEXMLの構文」の説明

例4-17 UPDATEおよびUPDATEXMLを使用したXMLTypeの更新

この例では、新しいXML文書を作成するのではなく、UPDATE文の右側にupdateXMLを使用して表内のXML文書を更新します。選択された部分のみではなく、文書全体が更新されます。

SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Actions/Action[1]') ACTION FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

ACTION
--------------------------------
<Action>
  <User>SVOLLMAN</User>
</Action>

1 row selected.

UPDATE purchaseorder
  SET OBJECT_VALUE = updateXML(OBJECT_VALUE, '/PurchaseOrder/Actions/Action[1]/User/text()', 'SKING')
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

1 row updated.

SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Actions/Action[1]') ACTION
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE,'/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

ACTION
---------------------------------
<Action>
  <User>SKING</User>
</Action>

1 row selected.

例4-18 UPDATEXMLを使用した、複数のテキスト・ノードと属性値の更新

この例では、SQL関数updateXMLを使用して複数のノードを更新します。

SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Requestor') NAME,
       extract(OBJECT_VALUE, '/PurchaseOrder/LineItems') LINEITEMS
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

NAME             LINEITEMS
---------------- ------------------------------------------------------------------------
Sarah J. Bell    <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>

1 row selected.

UPDATE purchaseorder
  SET OBJECT_VALUE = updateXML(OBJECT_VALUE,
                               '/PurchaseOrder/Requestor/text()', 'Stephen G. King',
                               '/PurchaseOrder/LineItems/LineItem[1]/Part/@Id', '786936150421',
                               '/PurchaseOrder/LineItems/LineItem[1]/Description/text()', 'The Rock',
                               '/PurchaseOrder/LineItems/LineItem[3]',
                               XMLType('<LineItem ItemNumber="99">
                                          <Description>Dead Ringers</Description>
                                          <Part Id="715515009249" UnitPrice="39.95" Quantity="2"/>
                                        </LineItem>'))
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

1 row updated.

SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Requestor') NAME,
       extract(OBJECT_VALUE, '/PurchaseOrder/LineItems') LINEITEMS
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

NAME             LINEITEMS
---------------- ------------------------------------------------------------------
Stephen G. King  <LineItems>
                   <LineItem ItemNumber="1">
                     <Description>The Rock</Description>
                     <Part Id="786936150421" 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="99">
                     <Description>Dead Ringers</Description>
                     <Part Id="715515009249" UnitPrice="39.95" Quantity="2"/>
                   </LineItem>
                 </LineItems>

1 row selected.

例4-19 UPDATEXMLを使用した、コレクション内で選択されたノードの更新

この例では、SQL関数updateXMLを使用して、コレクション内で選択されたノードを更新します。

SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Requestor') NAME,
       extract(OBJECT_VALUE, '/PurchaseOrder/LineItems') LINEITEMS
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

NAME             LINEITEMS
---------------- ------------------------------------------------------------------------
Sarah J. Bell    <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>

1 row selected.

UPDATE purchaseorder
  SET OBJECT_VALUE =
      updateXML(OBJECT_VALUE,
                '/PurchaseOrder/Requestor/text()', 'Stephen G. King',
                '/PurchaseOrder/LineItems/LineItem/Part[@Id="715515009058"]/@Quantity', 25,
                '/PurchaseOrder/LineItems/LineItem[Description/text()="The Unbearable Lightness Of Being"]',
                XMLType('<LineItem ItemNumber="99">
                           <Part Id="786936150421" Quantity="5" UnitPrice="29.95"/>
                           <Description>The Rock</Description>
                         </LineItem>'))
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

1 row updated.

SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Requestor') NAME,
       extract(OBJECT_VALUE, '/PurchaseOrder/LineItems') LINEITEMS
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

NAME             LINEITEMS
---------------- ------------------------------------------------------------------------
Stephen G. King  <LineItems>
                   <LineItem ItemNumber="1">
                     <Description>A Night to Remember</Description>
                     <Part Id="715515009058" UnitPrice="39.95" Quantity="25"/>
                   </LineItem>
                   <LineItem ItemNumber="99">
                     <Part Id="786936150421" Quantity="5" UnitPrice="29.95"/>
                     <Description>The Rock</Description>
                   </LineItem>
                   <LineItem ItemNumber="3">
                     <Description>Sisters</Description>
                     <Part Id="715515011020" UnitPrice="29.95" Quantity="4"/>
                   </LineItem>
                 </LineItems>

1 row selected.

UPDATEXMLおよびNULL値

XML要素をNULLに更新すると、要素の属性および子は削除され、その要素は空になります。要素のタイプおよび名前空間プロパティは保持されます。例4-20を参照してください。

属性値をNULLに更新すると、値は空の文字列として表示されます。例4-20を参照してください。

要素のテキスト・ノードをNULLに更新すると、その要素のコンテンツ(テキスト)は削除されます。要素自体は残りますが、空になります。例4-21を参照してください。

例4-20 UPDATEXMLを使用したNULL更新: 要素および属性

この例では、次のものすべてをNULLに更新します。

  • Description要素と、Part要素の属性Id値が715515009058のLineItem要素のQuantity属性

  • Description要素のコンテンツ(テキスト)が「The Unbearable Lightness Of Being」であるLineItem要素

SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Requestor') NAME,
       extract(OBJECT_VALUE, '/PurchaseOrder/LineItems') LINEITEMS
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

NAME             LINEITEMS
---------------- -------------------------------------------------------------------
Sarah J. Bell    <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>

1 row selected.

UPDATE purchaseorder
  SET OBJECT_VALUE =
      updateXML(
        OBJECT_VALUE,
        '/PurchaseOrder/LineItems/LineItem[Part/@Id="715515009058"]/Description', NULL,
        '/PurchaseOrder/LineItems/LineItem/Part[@Id="715515009058"]/@Quantity', NULL,
        '/PurchaseOrder/LineItems/LineItem[Description/text()="The Unbearable Lightness Of Being"]', NULL)
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

1 row updated.

SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Requestor') NAME,
       extract(OBJECT_VALUE, '/PurchaseOrder/LineItems') LINEITEMS
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]') = 1;

NAME             LINEITEMS
---------------- ----------------------------------------------------------------
Sarah J. Bell    <LineItems>
                   <LineItem ItemNumber="1">
                     <Description/>
                     <Part Id="715515009058" UnitPrice="39.95" Quantity=""/>
                   </LineItem>
                   <LineItem/>
                   <LineItem ItemNumber="3">
                     <Description>Sisters</Description>
                     <Part Id="715515011020" UnitPrice="29.95" Quantity="4"/>
                   </LineItem>
                 </LineItems>

1 row selected.

例4-21では、Description属性の値が「A Night to Remember」であるPart要素のテキスト・ノードをNULLに更新します。

例4-21 UPDATEXMLを使用したNULL更新: テキスト・ノード

この例のXMLデータは、修正された別の発注書XML Schemaに対応しています(「コピーに基づく拡張の使用例」を参照)。そのXML Schemaでは、DescriptionPart要素の属性であり、兄弟要素ではありません。

SELECT extractValue(OBJECT_VALUE,
                    '/PurchaseOrder/LineItems/LineItem/Part[@Description="A Night to Remember"]') PART
  FROM purchaseorder
  WHERE existsNode(object_value,'/PurchaseOrder[@Reference="SBELL-2003030912333601PDT"]') = 1;

PART
----
<Part Description="A Night to Remember" UnitCost="39.95">715515009058</Part>

UPDATE purchaseorder
  SET OBJECT_VALUE =
        updateXML(OBJECT_VALUE,
                  '/PurchaseOrder/LineItems/LineItem/Part[@Description="A Night to Remember"]/text()', NULL)
  WHERE existsNode(object_value,'/PurchaseOrder[@Reference="SBELL-2003030912333601PDT"]') = 1;


SELECT extractValue(OBJECT_VALUE,
                    '/PurchaseOrder/LineItems/LineItem/Part[@Description="A Night to Remember"]') PART
  FROM purchaseorder
  WHERE existsNode(object_value,'/PurchaseOrder[@Reference="SBELL-2003030912333601PDT"]') = 1;


PART
----
<Part Description="A Night to Remember" UnitCost="39.95"/>

関連項目:

updateXML式のリライト例は、例7-2例7-3および例3-35を参照してください。

同じXMLノードの複数回の更新

同じXMLノードをupdateXML式で複数回更新できます。たとえば、/EMP[EMPNO=217]/EMP[EMPNAME="Jane"]/EMPNOの両方を更新できます。この場合、1つ目のXPathはそれを含むEMPNOノードも識別します。更新の順序は、左から順に、XPath式の順序によって決定されます。各XPathは、その前のXPathの更新結果に基づいて機能します。

UPDATEXML使用時のDOM 再現性の保持

ここでは、SQL関数updateXMLを使用する際にDOM再現性を保持するためのガイドラインを示します。

DOM再現性が保持される場合

要素をNULLに更新する場合は、<myElem/>のように、その親で目的の要素が空に表示されるようにします。要素内のテキスト・ノードをNULLに更新する場合は、その要素からテキスト・ノードを削除します。属性ノードをNULLに更新する場合は、myAttr=""のように、属性の値が空の文字列になるようにします。

DOM再現性が保持されない場合

complexType要素をNULLに更新する場合は、<myElem/>のように、その親で目的の要素が空に表示されるようにします。SQLインラインsimpleType要素をNULLに更新する場合は、その親から要素が見えないようにします。テキスト・ノードをNULLに更新する場合は、親のsimpleType要素をNULLに設定する場合と同じ手順を実行します。また、複合的なコンテンツを格納する位置指定ディスクリプタがないため、DOM再現性が保持されない場合、テキスト・ノードはsimpleTypes要素内部でのみ出現できます。属性ノードをNULLに更新する場合は、要素からその属性を削除します。

DOM再現性が保持されるかどうかの判別

XML Schema内のXMLTypeの特定部分についてDOM再現性が保持されるかどうかを判別するには、属性maintainDOMのスキーマ・メタデータを問い合せます。


関連項目:


XMLデータを更新するSQL関数の最適化

ほとんどの場合、XMLデータを更新するSQL関数は、入力されたXML文書全体のコピーをメモリー内に生成してから、そのコピーを更新します。ただし、関数updateXMLinsertChildXMLinsertChildXMLbeforeinsertChildXMLafterおよびdeleteXML(つまり、insertXMLbeforeinsertXMLafterおよびappendChildXML以外)は、オブジェクト・リレーショナル形式またはバイナリXMLとして格納されているXMLType表および列に対するSQL UPDATE操作のために最適化されます。構造化記憶域の場合、特定の条件が満たされれば、関数コールは、オブジェクト・リレーショナル列を新しい値で直接更新するようにリライトできます。バイナリXML記憶域では、ターゲットとなっている更新以前のデータは変更されません。また、SecureFile LOBが使用されている場合は、スライド方式の挿入を使用して、変更が必要なデータ部分のみが更新されます。


関連項目:


オブジェクト・リレーショナル記憶域の例では、例4-22に記載されているupdateXMLへのXPath引数は、Oracle XML DBで処理され、例4-23に記載されている同等のオブジェクト・リレーショナルSQL文にリライトされます。

例4-22 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.

例4-23 UPDATEXML式と同等のオブジェクト・リレーショナル形式の文

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データを変更するSQL関数を使用した、XMLのビューの作成

XMLデータを変更するSQL関数(updateXMLinsertChildXMLinsertChildXMLbeforeinsertChildXMLafterinsertXMLbeforeinsertXMLafterappendChildXMLおよびdeleteXML)を使用して、XMLデータの新しいビューを作成できます。

例4-24 UPDATEXMLを使用したビューの作成

この例では、SQL関数updateXMLを使用してpurchaseorder表のビューを作成します。

CREATE OR REPLACE VIEW purchaseorder_summary OF XMLType AS
  SELECT updateXML(OBJECT_VALUE,
                   '/PurchaseOrder/Actions', NULL,
                   '/PurchaseOrder/ShippingInstructions', NULL,
                   '/PurchaseOrder/LineItems', NULL) AS XML
  FROM purchaseorder p;

View created.

SELECT OBJECT_VALUE FROM purchaseorder_summary
  WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder[Reference="DAUSTIN-20021009123335811PDT"]') = 1;

OBJECT_VALUE
---------------------------------------------------------------------------
<PurchaseOrder
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd">
  <Reference>DAUSTIN-20021009123335811PDT</Reference>
  <Actions/>
  <Reject/>
  <Requestor>David L. Austin</Requestor>
  <User>DAUSTIN</User>
  <CostCenter>S30</CostCenter>
  <ShippingInstructions/>
  <SpecialInstructions>Courier</SpecialInstructions>
  <LineItems/>
</PurchaseOrder>

1 row selected.

INSERTCHILDXML SQL関数

SQL関数insertChildXMLは、親のXML要素の下に新しい子(同じ型の1つ以上の要素、または単一の属性)を挿入します。挿入のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。

入力されたXMLTypeインスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。

関数insertChildXMLには、次のパラメータがあります(この順序どおり)。

  • target-dataXMLType): ターゲットの親要素を含むXMLデータ。

  • parent-xpath (VARCHAR2): target-datachild-data内部の親要素を検索するXPath 1.0式が、各親要素の下に挿入されます。

    parent-xpathが要素ノードの空シーケンスと一致する場合、挿入は行われません。target-dataがそのままの状態で戻されます(エラーは発生しません)。parent-xpathが要素ノードのシーケンスと一致しない場合(特に、parent-xpathが1つ以上の属性ノードまたはテキスト・ノードと一致する場合)、エラーが発生します。

  • child-nameVARCHAR2): 挿入する子要素または属性の名前。属性名は、child-nameの一部として先頭にアットマーク(@)が付くことで、要素名と区別されます。たとえば、属性名は@my_attribute、要素名はmy_elementのようになります。(アットマークは実際の属性名の一部ではありませんが、引数内でchild-nameが属性であることを示すはたらきをします。)

  • child-dataXMLTypeまたはVARCHAR2): 挿入する子XMLデータ。

    • 1つ以上の要素を挿入する場合、このパラメータのデータ型はXMLTypeであり、要素ノードを含みます。child-data内の最上位の要素ノードはそれぞれ、child-nameと同じ名前(タグ)を持つ必要があります(そうでない場合、エラーが発生します)。

    • 属性を挿入する場合、このパラメータのデータ型はVARCHAR2であり、(スカラー)属性値を表します。挿入位置に同じ名前の属性がすでに存在する場合、エラーが発生します。

  • namespaceVARCHAR2、オプション): パラメータparent-xpathおよびchild-dataのXML名前空間。

XMLデータchild-dataは、1つ以上の子要素として、または単一の子属性として、parent-xpathで見つかった各親要素の下に挿入されます。結果が戻されます。

NULL引数に対する関数insertChildXMLの動作は、次のとおりです(優先順位の高い順に示します)。

  • child-nameNULLの場合、エラーが発生します。

  • target-dataまたはparent-xpathNULLの場合、NULLが戻されます。

  • child-dataNULLの場合、次のようになります。

    • child-name名が要素名の場合、挿入は行われません。target-dataがそのままの状態で戻されます。

    • child-name名が属性名の場合、空の属性値が挿入されます。たとえば、my_attribute = ""になります。

図4-7に構文を示します。

図4-7 INSERTCHILDXMLの構文

図4-7の説明が続きます
「図4-7 INSERTCHILDXMLの構文」の説明

target-dataがXML Schemaに基づいている場合、そのスキーマを参照して挿入位置が決定されます。たとえば、スキーマがchild-nameという子要素をparent-xpathの最初の子要素に制限している場合、挿入はこれに基づいて行われます。同様に、child-nameまたはchild-data引数が、関連付けられたスキーマに対して不適切である場合は、エラーが発生します。

親要素がchild-nameに対応する名前および種類の子をまだ持っていない場合(かつ、関連付けられたXML Schemaが存在し、そのスキーマによってこのような子が許可されている場合)、child-dataが、新しい子要素として、または新しい属性値としてchild-nameという名前で挿入されます。

親要素がすでにchild-nameという名前(アットマークなし)の子属性を持つ場合は、エラーが発生します。親要素がすでにchild-nameという名前の子要素を持つ場合(かつ、関連付けられたXML Schemaが存在し、そのスキーマによって複数の子要素が許可されている場合)、child-dataは、その要素がchild-nameという名前の最後の子要素になるように挿入されます。

例4-25 LineItems要素へのLineItem要素の挿入

SELECT extract(OBJECT_VALUE,
               '/PurchaseOrder/LineItems/LineItem[@ItemNumber="222"]')
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;

EXTRACT(OBJECT_VALUE,'/PURCHASEORDER/LINEITEMS/LINEITEM[@ITEMNUMBER="222"]')
----------------------------------------------------------------------------

1 row selected.

UPDATE purchaseorder
  SET OBJECT_VALUE =
        insertChildXML(OBJECT_VALUE,
                       '/PurchaseOrder/LineItems',
                       'LineItem',
                       XMLType('<LineItem ItemNumber="222">
                                  <Description>The Harder They Come</Description>
                                  <Part Id="953562951413"
                                        UnitPrice="22.95"
                                        Quantity="1"/>
                                </LineItem>'))
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;

1 row updated.

SELECT extract(OBJECT_VALUE,
               '/PurchaseOrder/LineItems/LineItem[@ItemNumber="222"]')
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;

EXTRACT(OBJECT_VALUE,'/PURCHASEORDER/LINEITEMS/LINEITEM[@ITEMNUMBER="222"]')
----------------------------------------------------------------------------
<LineItem ItemNumber="222">
  <Description>The Harder They Come</Description>
  <Part Id="953562951413" UnitPrice="22.95" Quantity="1"/>
</LineItem>

1 row selected.

更新されるXMLデータがXML Schemaに基づいており、名前空間を参照している場合、挿入されるデータも同じ名前空間を参照している必要があります。そうでない場合、挿入されたデータがXML Schemaに準拠していないために、エラーが発生します。たとえば、例4-25のデータが名前空間films.xsdを使用しているとすると、UPDATE文は例4-26に示すとおりにする必要があります。

例4-26 名前空間を使用する要素の挿入

この例は例4-25と似ていますが、挿入されるLineItem要素が名前空間を参照しています。これは、XML Schemaでこの要素に対する名前空間が必要であることを前提としています。

このような名前空間の使用は、関数insertChildXMLへの名前空間引数の使用とは異なりますので注意してください。そのオプションの引数に指定された名前空間は、挿入されるコンテンツではなく、XPath引数のみに適用されます。

UPDATE purchaseorder
  SET OBJECT_VALUE =
        insertChildXML(OBJECT_VALUE,
                       '/PurchaseOrder/LineItems',
                       'LineItem',
                       XMLType('<LineItem xmlns="films.xsd" ItemNumber="222">
                                  <Description>The Harder They Come</Description>
                                  <Part Id="953562951413"
                                        UnitPrice="22.95"
                                        Quantity="1"/>
                                </LineItem>'))
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;

1 row updated.

INSERTCHILDXMLBEFORE SQL関数

SQL関数insertChildXMLbeforeは、1つ以上のコレクション要素をターゲットの親要素の子として挿入します。各ターゲットは、指定された既存のコレクション要素の直前に挿入されます。挿入のターゲットである既存のXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。

入力されたXMLTypeインスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。

関数insertChildXMLbeforeには、次のパラメータがあります(この順序どおり)。

  • target-dataXMLType): 挿入のターゲットであるXMLデータ。

  • parent-xpath (VARCHAR2): target-datachild-data内部の親要素を検索するXPath 1.0式が、各親要素の下に挿入されます。

    parent-xpathが要素ノードの空シーケンスと一致する場合、挿入は行われません。target-dataがそのままの状態で戻されます(エラーは発生しません)。parent-xpathが要素ノードのシーケンスと一致しない場合(特に、parent-xpathが1つ以上の属性ノードまたはテキスト・ノードと一致する場合)、エラーが発生します。

  • child-xpathVARCHAR2): 挿入されるchild-dataの直後の位置の既存の子を検索する相対XPath 1.0式。この式は、parent-xpathに示された要素の子要素の名前を指定している必要があります。この式には、述語を含めることもできます。

  • child-dataXMLType): 挿入する子要素XMLデータ。このデータ型は常にXMLTypeであり、要素ノードを含んでいます。child-data内の最上位の要素ノードはそれぞれ、child-nameに示された要素と同じデータ型を持つ必要があります(そうでない場合、エラーが発生します)。

  • namespace(オプション、VARCHAR2): パラメータparent-xpathchild-xpathおよびchild-dataの名前空間。

XMLデータchild-dataは、1つ以上の子要素として、parent-xpathで見つかった各親要素の下に挿入されます。結果が戻されます。

NULL引数に対する関数insertChildXMLbeforeの動作は、次のとおりです(優先順位の高い順に示します)。

  • child-nameNULLの場合、エラーが発生します。

  • target-dataまたはparent-xpathNULLの場合、NULLが戻されます。

  • child-dataNULLの場合、挿入は行われません。target-dataがそのままの状態で戻されます。

図4-8に構文を示します。

図4-8 INSERTCHILDXMLBEFOREの構文

図4-8の説明が続きます
「図4-8 INSERTCHILDXMLBEFOREの構文」の説明

INSERTCHILDXMLAFTER SQL関数

SQL関数insertChildXMLafterは、1つ以上のコレクション要素をターゲットの親要素の子として挿入します。各ターゲットは、指定された既存のコレクション要素の直後に挿入されます。挿入のターゲットである既存のXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。

入力されたXMLTypeインスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。

関数insertChildXMLafterには、次のパラメータがあります(この順序どおり)。

  • target-dataXMLType): 挿入のターゲットであるXMLデータ。

  • parent-xpath (VARCHAR2): target-datachild-data内部の親要素を検索するXPath 1.0式が、各親要素の下に挿入されます。

    parent-xpathが要素ノードの空シーケンスと一致する場合、挿入は行われません。target-dataがそのままの状態で戻されます(エラーは発生しません)。parent-xpathが要素ノードのシーケンスと一致しない場合(特に、parent-xpathが1つ以上の属性ノードまたはテキスト・ノードと一致する場合)、エラーが発生します。

  • child-xpathVARCHAR2): 挿入されるchild-dataの直前の位置の既存の子を検索する相対XPath 1.0式。この式は、parent-xpathに示された要素の子要素の名前を指定している必要があります。この式には、述語を含めることもできます。

  • child-dataXMLType): 挿入する子要素XMLデータ。このデータ型は常にXMLTypeであり、要素ノードを含んでいます。child-data内の最上位の要素ノードはそれぞれ、child-nameに示された要素と同じデータ型を持つ必要があります(そうでない場合、エラーが発生します)。

  • namespace(オプション、VARCHAR2): パラメータparent-xpathchild-xpathおよびchild-dataの名前空間。

XMLデータchild-dataは、1つ以上の子要素として、parent-xpathで見つかった各親要素の下に挿入されます。結果が戻されます。

NULL引数に対する関数insertChildXMLafterの動作は、次のとおりです(優先順位の高い順に示します)。

  • child-nameNULLの場合、エラーが発生します。

  • target-dataまたはparent-xpathNULLの場合、NULLが戻されます。

  • child-dataNULLの場合、挿入は行われません。target-dataがそのままの状態で戻されます。

図4-9に構文を示します。

図4-9 INSERTCHILDXMLAFTERの構文

図4-9の説明が続きます
「図4-9 INSERTCHILDXMLAFTERの構文」の説明

INSERTXMLBEFORE SQL関数

SQL関数insertXMLbeforeは、任意の種類の1つ以上のノードを、属性ノード以外のターゲット・ノードの直前に挿入します。挿入のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。

入力されたXMLTypeインスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。

関数insertXMLbeforeには、次のパラメータがあります(この順序どおり)。

  • target-dataXMLType): 挿入のターゲットであるXMLデータ。

  • successor-xpathVARCHAR2): 属性ノード以外の種類のtarget-data内で0個以上のノードを検索するXPath 1.0式。XML-dataは、これらの各ノードの直前に挿入されます。つまり、XML-data内のノードが、各successor-xpathノードの前の兄弟ノードになります。

    successor-xpathがノードの空のシーケンスと一致する場合、挿入は行われません。target-dataがそのままの状態で戻されます(エラーは発生しません)。successor-xpathが、属性ノード以外のノードのシーケンスと一致する場合、エラーが発生します。

  • XML-dataXMLType): 挿入されるXMLデータ。任意の種類の1つ以上のノードです。ノードの順序は、挿入後も保持されます。

  • namespace(オプション、VARCHAR2): パラメータsuccessor-xpathの名前空間。

XML-dataノードは、successor-xpathで見つかった属性以外のノードそれぞれの直前に挿入されます。結果が戻されます。

関数insertXMLbeforeNULL引数に対する動作は、次のとおりです。

  • target-dataまたはparent-xpathNULLの場合、NULLが戻されます。

  • それ以外の場合、child-dataNULLであれば、挿入は行われません。target-dataがそのままの状態で戻されます。

図4-10に構文を示します。

図4-10 INSERTXMLBEFOREの構文

図4-10の説明が続きます
「図4-10 INSERTXMLBEFOREの構文」の説明

例4-27 最初のLineItem要素の直前にLineItem要素を挿入

SELECT extract(OBJECT_VALUE, '/PurchaseOrder/LineItems/LineItem[1]')
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;

EXTRACT(OBJECT_VALUE,'/PURCHASEORDER/LINEITEMS/LINEITEM[1]')
------------------------------------------------------------
<LineItem ItemNumber="1">
  <Description>Salesman</Description>
  <Part Id="37429158920" UnitPrice="39.95" Quantity="2"/>
</LineItem>

1 row selected.

UPDATE purchaseorder
  SET OBJECT_VALUE =
      insertXMLbefore(OBJECT_VALUE,
                      '/PurchaseOrder/LineItems/LineItem[1]',
                      XMLType('<LineItem ItemNumber="314">
                                 <Description>Brazil</Description>
                                 <Part Id="314159265359"
                                       UnitPrice="69.95"
                                       Quantity="2"/>
                               </LineItem>'))
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;

SELECT extract(OBJECT_VALUE, '/PurchaseOrder/LineItems/LineItem[position() <= 2]')
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;

EXTRACT(OBJECT_VALUE,'/PURCHASEORDER/LINEITEMS/LINEITEM[POSITION()<=2]')
------------------------------------------------------------------------
<LineItem ItemNumber="314">
  <Description>Brazil</Description>
  <Part Id="314159265359" UnitPrice="69.95" Quantity="2"/>
</LineItem>
<LineItem ItemNumber="1">
  <Description>Salesman</Description>
  <Part Id="37429158920" UnitPrice="39.95" Quantity="2"/>
</LineItem>

1 row selected.

INSERTXMLAFTER SQL関数

SQL関数insertXMLafterは、任意の種類の1つ以上のノードを、属性ノード以外のターゲット・ノードの直後に挿入します。挿入のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。この点ではinsertXMLbeforeに似ていますが、ターゲット・ノードの直前ではなく直後に挿入する点が異なります。

入力されたXMLTypeインスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。

関数insertXMLafterには、次のパラメータがあります(この順序どおり)。

  • target-dataXMLType): 挿入のターゲットであるXMLデータ。

  • successor-xpathVARCHAR2): 属性ノード以外の種類のtarget-data内で0個以上のノードを検索するXPath 1.0式。XML-dataは、これらの各ノードの直後に挿入されます。つまり、XML-data内のノードが、各successor-xpathノードの後の兄弟ノードになります。

    successor-xpathがノードの空のシーケンスと一致する場合、挿入は行われません。target-dataがそのままの状態で戻されます(エラーは発生しません)。successor-xpathが、属性ノード以外のノードのシーケンスと一致する場合、エラーが発生します。

  • XML-dataXMLType): 挿入されるXMLデータ。任意の種類の1つ以上のノードです。ノードの順序は、挿入後も保持されます。

  • namespace(オプション、VARCHAR2): パラメータsuccessor-xpathの名前空間。

XML-dataノードは、successor-xpathで見つかった属性以外のノードそれぞれの直後に挿入されます。結果が戻されます。

関数insertXMLafterNULL引数に対する動作は、次のとおりです。

  • target-dataまたはparent-xpathNULLの場合、NULLが戻されます。

  • それ以外の場合、child-dataNULLであれば、挿入は行われません。target-dataがそのままの状態で戻されます。

図4-11に構文を示します。

図4-11 INSERTXMLAFTERの構文

図4-11の説明が続きます
「図4-11 INSERTXMLAFTERの構文」の説明

APPENDCHILDXML SQL関数

SQL関数appendChildXMLは、任意の種類の1つ以上のノードを、指定された要素ノードの最後の子として挿入します。挿入のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。

入力されたXMLTypeインスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。

関数appendChildXMLには、次のパラメータがあります(この順序どおり)。

  • target-dataXMLType): ターゲットの親要素を含むXMLデータ。

  • parent-xpathVARCHAR2): 挿入操作のターゲットであるtarget-data内で0個以上の要素ノードを検索するXPath 1.0式。child-dataは、これらの各親要素の最後の子として挿入されます。

    parent-xpathが要素ノードの空シーケンスと一致する場合、挿入は行われません。target-dataがそのままの状態で戻されます(エラーは発生しません)。parent-xpathが要素ノードのシーケンスと一致しない場合(特に、parent-xpathが1つ以上の属性ノードまたはテキスト・ノードと一致する場合)、エラーが発生します。

  • child-dataXMLType): 挿入される子データ。任意の種類の1つ以上のノードです。ノードの順序は、挿入後も保持されます。

  • namespace(オプション、VARCHAR2): パラメータparent-xpathの名前空間。

XMLデータchild-dataは、parent-xpathにより指定された各要素ノードの最後の子として挿入されます。結果が戻されます。

関数appendChildXMLNULL引数に対する動作は、次のとおりです。

  • target-dataまたはparent-xpathNULLの場合、NULLが戻されます。

  • それ以外の場合、child-dataNULLであれば、挿入は行われません。target-dataがそのままの状態で戻されます。

図4-12に構文を示します。

図4-12 APPENDCHILDXMLの構文

図4-12の説明が続きます
「図4-12 APPENDCHILDXMLの構文」の説明

例4-28 Action要素の最後の子としてDate要素を挿入

SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Actions/Action[1]')
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;

EXTRACT(OBJECT_VALUE,'/PURCHASEORDER/ACTIONS/ACTION[1]')
--------------------------------------------------------
<Action>
  <User>KPARTNER</User>
</Action>

1 row selected.

UPDATE purchaseorder
  SET OBJECT_VALUE =
      appendChildXML(OBJECT_VALUE,
                     '/PurchaseOrder/Actions/Action[1]',
                     XMLType('<Date>2002-11-04</Date>'))
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;

SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Actions/Action[1]')
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;

EXTRACT(OBJECT_VALUE,'/PURCHASEORDER/ACTIONS/ACTION[1]')
--------------------------------------------------------
<Action>
  <User>KPARTNER</User>
  <Date>2002-11-04</Date>
</Action>

1 row selected.

DELETEXML SQL関数

SQL関数deleteXMLは、任意の種類のXMLノードを削除します。削除のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。

入力されたXMLTypeインスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。

関数deleteXMLには、次のパラメータがあります(この順序どおり)。

  • target-dataXMLType): (削除される)ターゲット・ノードを含むXMLデータ。

  • xpathVARCHAR2): 削除操作のターゲットであるtarget-data内で0個以上のノードを検索するXPath 1.0式。これらのノードはすべて削除されます。

    xpathがノードの空シーケンスと一致する場合、削除は行われません。target-dataがそのままの状態で戻されます(エラーは発生しません)。xpathが最上位の要素ノードと一致する場合、エラーが発生します。

  • namespace(オプション、VARCHAR2): パラメータxpathの名前空間。

xpathで見つかったXMLノードがtarget-dataから削除されます。結果が戻されます。target-dataまたはxpathNULLの場合、関数deleteXMLNULLを戻します。

図4-13に構文を示します。

図4-13 DELETEXMLの構文

図4-13の説明が続きます
「図4-13 DELETEXMLの構文」の説明

例4-29 LineItem要素(番号222)の削除

SELECT extract(OBJECT_VALUE,
               '/PurchaseOrder/LineItems/LineItem[@ItemNumber="222"]')
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;
EXTRACT(OBJECT_VALUE,'/PURCHASEORDER/LINEITEMS/LINEITEM[@ITEMNUMBER="222"]')
----------------------------------------------------------------------------
<LineItem ItemNumber="222">
  <Description>The Harder They Come</Description>
  <Part Id="953562951413" UnitPrice="22.95" Quantity="1"/>
</LineItem>

1 row selected.

UPDATE purchaseorder
  SET OBJECT_VALUE =
      deleteXML(OBJECT_VALUE,
                '/PurchaseOrder/LineItems/LineItem[@ItemNumber="222"]')
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;

SELECT extract(OBJECT_VALUE,
               '/PurchaseOrder/LineItems/LineItem[@ItemNumber="222"]')
  FROM purchaseorder
  WHERE existsNode(OBJECT_VALUE,
                   '/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]')
        = 1;
EXTRACT(OBJECT_VALUE,'/PURCHASEORDER/LINEITEMS/LINEITEM[@ITEMNUMBER="222"]')
----------------------------------------------------------------------------

1 row selected.