この章では、XMLアプリケーションに対するXMLType
の操作(XML Schemaに基づく、およびXML Schemaに基づかない)について説明します。XMLType
列および表の作成、操作、更新、および問合せに関するガイドラインも含まれています。
この章の内容は次のとおりです。
関連項目:
|
次の方法で、XMLType
列からXMLデータを問い合せることができます。
SQL、PL/SQLまたはJavaでXMLType
列を選択する方法。
直接、またはXMLType
メソッドextract()
およびexistsNode()
を使用して、XMLType
列を問い合せる方法。
Oracle Text演算子を使用してXMLコンテンツを問い合せる方法。第5章「XMLTypeデータの索引付け」および第11章「XMLデータの全文検索」を参照してください。
XQuery言語を使用する方法。「XQueryのXMLTypeデータとの使用」を参照してください。
XPath言語は、XML文書をナビゲートするためのW3C勧告です。XPathは、XML文書をノードのツリーとしてモデル化します。XPathには、このツリー内を移動し、述語およびノード・テスト関数を適用するための豊富な操作が備わっています。XPath式をXML文書に適用すると、ノードの集合が戻されます。たとえば、式/PO/PONO
は、文書のPO
ルート要素の下にあるすべてのPONO
子要素を選択します。
注意: Oracle SQL関数およびXMLType メソッドは、W3CのXPath勧告に準拠しています。これは、XPath式をXMLデータに適用する際にXPath式がどのノードもターゲットにしていない場合、空のシーケンスが戻される必要がある、つまり、エラーが発生してはいけないことを規定したものです。
XPath式をXMLデータに適用するOracle SQL関数または |
表4-1に、XPathで使用する共通構造体を示します。
XPath構造体 | 説明 |
---|---|
|
XPath式のツリーのルートを示します。たとえば、 |
|
任意のノードの子ノードを識別するための区切りとしても使用します。たとえば、 |
|
現行ノードのすべての子孫を識別するために使用します。たとえば、 |
|
任意の子ノードと一致させるためのワイルド・カードとして使用します。たとえば、 |
|
述語式を示すために使用します。XPathは 大カッコは、位置(索引)を示す場合にも使用します。たとえば、 |
関数 |
XPathは、 |
XPathは単一のノードまたは一連の要素、テキストまたは属性ノードを識別する必要があります。XPathの結果はブール式にはできません。
XMLType
データは、PL/SQL、CまたはJavaを使用して選択できます。XMLType
メソッドgetCLOBVal()
、getStringVal()
、getNumberVal()
およびgetBLOBVal(csid)
を使用して、XMLデータをそれぞれCLOB
、VARCHAR
、NUMBER
および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.
次のSQL関数を使用すると、XMLType
データを問い合せて一部を抽出できます。
SQL/XML標準関数XMLQuery
、XMLTable
、XMLExists
およびXMLCast
Oracle関数existsNode
、extract
およびextractValue
Oracle関数は、W3CのXPath勧告のサブセットを使用して文書をナビゲートします。XMLQuery
関数およびXMLTable
関数の詳細は、第18章「Oracle XML DBでのXQueryの使用」を参照してください。他の関数については、次の各項で説明します。
図4-1に、SQL/XMLの標準関数XMLExists
の構文を示します。この関数は、所定のXQuery式が空でないXQueryシーケンスを戻すかどうかを確認します。空でない場合、この関数はTRUE
を戻します。空の場合はFALSE
を戻します。
XML_passing_clause::=
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
をコールした場合、XMLExists
はfalse
を戻します。
関数XMLExists
は、問合せ内で使用できます。また、問合せの評価を高速化するためのファンクション索引を作成する場合にも使用できます。
注意: Oracle XML DBは、XMLExists の使用をSQLのWHERE 句またはCASE 式に制限します。XMLExists をSELECT リストの中で使用する必要がある場合は、次のようにそれをCASE 式でラップします。
CASE WHEN XMLExists(...) THEN 'TRUE' ELSE 'FALSE' END |
例4-2 XMLExistsを使用したノードの検索
この例では、SQL/XML標準関数XMLExists
を使用して、SpecialInstructions
がExpedite
に設定されている行を選択します。同じことを実行する際に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検索を高速化することもできます。
図4-2に、SQL関数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ブール値を戻します。existsNode
は1
または0
を戻します。
/PurchaseOrder/Reference
または/PurchaseOrder/Reference/text()
のようなXPath式が、単一のノードをターゲットとする場合、existsNode
はその式に1
を戻します。どのノードも検索しないXPath式を使用してexistsNode
をコールした場合、existsNode
は0
を戻します。
関数existsNode
は、問合せ内で使用できます。また、問合せの評価を高速化するためのファンクション索引を作成する場合にも使用できます。
注意: 問合せにSQL関数existsNode を使用する場合は、必ず、SELECT リストではなくWHERE 句内で指定してください。 |
例4-3 EXISTSNODEを使用したノードの検索
この例では、SQL関数existsNode
を使用して、SpecialInstructions
がExpedite
に設定されている行を選択します。同じことを実行する際に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検索を高速化することもできます。
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;
注意: extract のかわりに、SQL/XML関数XMLQuery を使用することもできます。Oracle特有の関数ではなく標準関数なので、通常はXMLQuery の使用をお薦めします。 |
extract
をXMLType
値に適用すると、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 インスタンスを戻します。
メソッド |
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]
<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パスの適用によって空のセットが生成される場合、extract
はNULL
値を戻します。
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関数extractValue とXMLType メソッドgetStringVal() では、エンティティのエンコーディングの処理方法が異なります。関数extractValue はエンコードされたエンティティをエスケープしませんが、メソッドgetStringVal() はエンティティのエンコーディングを完全な状態で保持したデータを戻します。 |
図4-4に、SQL/XMLの標準関数XMLCast
の構文を示します。
SQL/XML標準関数XMLCast
は、その最初の引数を2番目の引数で指定されるSQLスカラー・データ型にキャストします。最初の引数は、評価されるSQL式です。データ型NUMBER
、VARCHAR2
、および任意の日時データ型を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検索を高速化することもできます。
SQL関数extractValue
は、XMLType
インスタンスと、ノード・セットをターゲットとするXPath式をパラメータとして取ります。この関数は、XMLType
インスタンスのXPath評価の結果に対応するSQLスカラー値を戻します。
XML Schemaに基づく文書: XML Schemaに基づく文書では、Oracle Databaseが戻り値の型を推測できる場合、該当する型のスカラー値が戻されます。それ以外の場合、結果はVARCHAR2
型です。
スキーマに基づかない文書: 問合せがSQL/XMLビューにある場合など、extractValue
がリライトされる可能性がある場合は、該当する型のスカラー値が戻されます。それ以外の場合、結果はVARCHAR2
型です。
図4-5に、extractValue
の構文を示します。
SQL関数extractValue
は、文書に関連付けられたXML Schemaや、SQL/XMLビューなどの他の情報から、正しい戻り型を判断しようとします。正しい戻り型が判断できない場合、Oracle XML DBはVARCHAR2
を戻します。XML Schemaに基づくコンテンツでは、extractValue
は多くの場合、基礎となるデータ型を戻します。CLOB
値は直接戻されます。
特定のデータ型が必要な場合は、extractValue
またはextract.getStringVal()
の結果に対してto_char
やto_date
などの変換関数を適用できます。これは、問合せがリライト可能かどうかに関係なく、複数の異なる問合せ間で一貫性を保持するために役立ちます。
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
の構文と同じです。
SQL関数extractValue
には、次のような特性があります。
スカラー値(NUMBER
、VARCHAR2
など)のみを戻します。XMLノードまたは複合的なコンテンツを戻すことはできません。extractValueがスカラー値を戻すことができない場合、エラーが発生します。
デフォルトでは、extractValueはVARCHAR2
値を戻します。長さが4Kを超える場合、ランタイム・エラーが発生します。
問合せのコンパイル時にXML Schema情報が使用可能な場合、そのXML Schema情報に基づいて、戻される値のデータ型が決まります。たとえば、XPath /PurchaseOrder/LineItems/LineItem[1]/Part/@Quantity
のXML Schema情報に数値が指定されている場合、extractValue
はNUMBER
を戻します。
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.
注意: 関数extractValue とXMLType メソッドgetStringVal() では、エンティティのエンコーディングの処理方法が異なります。関数extractValue はエンコードされたエンティティをエスケープしませんが、メソッドgetStringVal() はエンティティのエンコーディングを完全な状態で保持したデータを戻します。 |
例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データを問い合せる方法を示します。
例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.
この例では、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データの更新について説明します。次のSQL関数の使用方法を詳しく説明します。
updateXML
insertChildXML
insertChildXMLbefore
insertChildXMLafter
insertXMLbefore
insertXMLafter
appendChildXML
deleteXML
未構造化記憶域(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データを付加的に更新する(周囲の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データを挿入するには、関数insertChildXML
、insertXMLbefore
、insertChildXMLafter
、insertXMLbefore
、insertXMLafter
および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関数または |
XMLノードを既存のXMLデータ(のコピー)に挿入するためのSQL関数がいくつかあります。いずれも、XPath式により参照されるノードを複数の場所に挿入できます。各関数は、新しいノードの挿入位置と、ターゲットXMLデータの参照方法が異なります。
関数appendChildXML
は、ターゲット要素にノードを追加します。つまり、ターゲット要素ごとに、任意の種類の1つ以上のノードを要素の最後の子として挿入します。
関数insertChildXML
は、ターゲット要素の下に新しい子(同じ型の1つ以上の要素、または単一の属性)を挿入します。親の下の新しい子要素の位置は指定されません。ターゲット・データがXML Schemaに基づいている場合、そのスキーマを使用して挿入位置を指定できる場合もあります。できない場合、挿入位置は任意です。
関数insertXMLbefore
は、任意の種類の1つ以上のノードを、(属性ノード以外の)ターゲット・ノードの直前に挿入します。
関数insertXMLafter
も同様にノードを挿入しますが、ターゲットの直前ではなく直後に挿入します。
関数insertChildXMLbefore
はinsertChildXML
と似ていますが、挿入されるノードが(属性でなく)要素である必要があることと、兄弟関係における新しい要素の位置をユーザーが指定する点が異なります。また、insertXMLbefore
と似ていますが、任意の要素ではなくコレクション要素のみを挿入する点が異なります。挿入位置により、後続のコレクション・メンバーが指定されます。挿入する実際の要素は、コレクションの要素型に対応している必要があります。
関数insertChildXMLafter
も同様にノードを挿入しますが、ターゲットの直前ではなく直後に挿入します。
insertChildXMLbefore
(insertChildXMLafter
)とinsertXMLbefore
(insertXMLbeforeafter
)は結果は似ていますが、ターゲットの場所の表現方法が異なります。前者の関数では、ターゲットは新しい子の親です。後者の関数では、ターゲットは後ろの(または前の)兄弟です。この違いは、関数名(Child
)に表れています。
たとえば、新しいLineItem
要素を、/PurchaseOrder/LineItems
要素の3つ下にあるLineItem
要素の前に挿入する場合、insertChildXMLbefore
を使用し、ターゲットの親を/PurchaseOrder/LineItems
として指定し、後続の兄弟をLineItem[3]
として指定します。または、insertXMLbefore
を使用し、ターゲットの後続の兄弟を/PurchaseOrder/LineItems/LineItem[3]
として指定することもできます。insertChildXML
を使用して挿入する場合は、コレクション内の新しい要素の位置を指定できません。結果の位置は不確定です。
さらに、これらの関数のうち、insertXMLbefore
、insertXMLafter
およびappendChildXML
以外はすべて、オブジェクト・リレーショナル形式またはバイナリXMLとして格納されているXMLType
表および列に対するSQL UPDATE
操作のために最適化されます。
SQL関数updateXML
は、任意の種類のXMLノードを置換します。更新のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力されたXMLType
インスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATE
を実行し、データベース・データを更新できます。
関数updateXML
には、次のパラメータがあります(この順序どおり)。
target-data
(XMLType
): 置換するターゲット・ノードを含むXMLデータ。
1つ以上の、xpath
パラメータとreplacement
パラメータの組。
xpath
(VARCHAR2
): 置換するtarget-data
内のノードを検索するXPath 1.0式。ターゲットのノードはそれぞれ、replacement
で置換されます。これらは、どのような種類のノードでもかまいません。xpath
がノードの空シーケンスと一致する場合、置換は行われません。target-data
がそのままの状態で戻されます(エラーは発生しません)。
replacement
(XMLType
またはVARCHAR2
): xpath
でターゲットとなっているデータを置換するXMLデータ。replacement
のデータ型は、置換されるデータと一致している必要があります。xpath
の置換のターゲットが要素ノードの場合、データ型はXMLType
である必要があります。xpath
のターゲットが属性ノードまたはテキスト・ノードの場合、データ型はVARCHAR2
である必要があります。属性ノードの場合、replacement
は、名前を含む完全な属性ノード(たとえば、my_attribute="23"
)ではなく、属性の置換値のみ(たとえば、23)です。
namespace
(VARCHAR2
、オプション): パラメータxpath
のXML名前空間。
SQL関数updateXML
を使用すると、既存の要素、属性およびその他のノードを新しい値で置換できます。この方法は、新しいノードを挿入したり、既存のノードを削除する方法として効率的ではありません。挿入および更新は、updateXML
を使用して、挿入または削除されるノードの親であるノード全部を置換することによってのみ実行できます。
関数updateXML
は、メモリー内の一時XMLインスタンスのみを更新します。表に格納されたデータを更新するには、SQLのUPDATE
文を使用します。
図4-6に構文を示します。
例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.
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では、Description
はPart
要素の属性であり、兄弟要素ではありません。
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"/>
同じXMLノードをupdateXML
式で複数回更新できます。たとえば、/EMP[EMPNO=217]
と/EMP[EMPNAME="Jane"]/EMPNO
の両方を更新できます。この場合、1つ目のXPathはそれを含むEMPNO
ノードも識別します。更新の順序は、左から順に、XPath式の順序によって決定されます。各XPathは、その前のXPathの更新結果に基づいて機能します。
ここでは、SQL関数updateXML
を使用する際にDOM再現性を保持するためのガイドラインを示します。
要素をNULL
に更新する場合は、<myElem/>
のように、その親で目的の要素が空に表示されるようにします。要素内のテキスト・ノードをNULL
に更新する場合は、その要素からテキスト・ノードを削除します。属性ノードをNULL
に更新する場合は、myAttr=""
のように、属性の値が空の文字列になるようにします。
complexType
要素をNULL
に更新する場合は、<myElem/>
のように、その親で目的の要素が空に表示されるようにします。SQLインラインsimpleType
要素をNULL
に更新する場合は、その親から要素が見えないようにします。テキスト・ノードをNULL
に更新する場合は、親のsimpleType
要素をNULL
に設定する場合と同じ手順を実行します。また、複合的なコンテンツを格納する位置指定ディスクリプタがないため、DOM再現性が保持されない場合、テキスト・ノードはsimpleTypes
要素内部でのみ出現できます。属性ノードをNULL
に更新する場合は、要素からその属性を削除します。
ほとんどの場合、XMLデータを更新するSQL関数は、入力されたXML文書全体のコピーをメモリー内に生成してから、そのコピーを更新します。ただし、関数updateXML
、insertChildXML
、insertChildXMLbefore
、insertChildXMLafter
およびdeleteXML
(つまり、insertXMLbefore
、insertXMLafter
および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関数(updateXML
、insertChildXML
、insertChildXMLbefore
、insertChildXMLafter
、insertXMLbefore
、insertXMLafter
、appendChildXML
および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.
SQL関数insertChildXML
は、親のXML要素の下に新しい子(同じ型の1つ以上の要素、または単一の属性)を挿入します。挿入のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力されたXMLType
インスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATE
を実行し、データベース・データを更新できます。
関数insertChildXML
には、次のパラメータがあります(この順序どおり)。
target-data
(XMLType
): ターゲットの親要素を含むXMLデータ。
parent-xpath
(VARCHAR2
): target-data
、child-data
内部の親要素を検索するXPath 1.0式が、各親要素の下に挿入されます。
parent-xpath
が要素ノードの空シーケンスと一致する場合、挿入は行われません。target-data
がそのままの状態で戻されます(エラーは発生しません)。parent-xpath
が要素ノードのシーケンスと一致しない場合(特に、parent-xpath
が1つ以上の属性ノードまたはテキスト・ノードと一致する場合)、エラーが発生します。
child-name
(VARCHAR2
): 挿入する子要素または属性の名前。属性名は、child-name
の一部として先頭にアットマーク(@
)が付くことで、要素名と区別されます。たとえば、属性名は@my_attribute
、要素名はmy_element
のようになります。(アットマークは実際の属性名の一部ではありませんが、引数内でchild-name
が属性であることを示すはたらきをします。)
child-data
(XMLType
またはVARCHAR2
): 挿入する子XMLデータ。
1つ以上の要素を挿入する場合、このパラメータのデータ型はXMLType
であり、要素ノードを含みます。child-data
内の最上位の要素ノードはそれぞれ、child-name
と同じ名前(タグ)を持つ必要があります(そうでない場合、エラーが発生します)。
属性を挿入する場合、このパラメータのデータ型はVARCHAR2
であり、(スカラー)属性値を表します。挿入位置に同じ名前の属性がすでに存在する場合、エラーが発生します。
namespace
(VARCHAR2
、オプション): パラメータparent-xpath
およびchild-data
のXML名前空間。
XMLデータchild-data
は、1つ以上の子要素として、または単一の子属性として、parent-xpath
で見つかった各親要素の下に挿入されます。結果が戻されます。
NULL
引数に対する関数insertChildXML
の動作は、次のとおりです(優先順位の高い順に示します)。
child-name
がNULL
の場合、エラーが発生します。
target-data
またはparent-xpath
がNULL
の場合、NULL
が戻されます。
child-data
がNULL
の場合、次のようになります。
child-name
名が要素名の場合、挿入は行われません。target-data
がそのままの状態で戻されます。
child-name
名が属性名の場合、空の属性値が挿入されます。たとえば、my_attribute =
""
になります。
図4-7に構文を示します。
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.
SQL関数insertChildXMLbefore
は、1つ以上のコレクション要素をターゲットの親要素の子として挿入します。各ターゲットは、指定された既存のコレクション要素の直前に挿入されます。挿入のターゲットである既存のXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力されたXMLType
インスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATE
を実行し、データベース・データを更新できます。
関数insertChildXMLbefore
には、次のパラメータがあります(この順序どおり)。
target-data
(XMLType
): 挿入のターゲットであるXMLデータ。
parent-xpath
(VARCHAR2
): target-data
、child-data
内部の親要素を検索するXPath 1.0式が、各親要素の下に挿入されます。
parent-xpath
が要素ノードの空シーケンスと一致する場合、挿入は行われません。target-data
がそのままの状態で戻されます(エラーは発生しません)。parent-xpath
が要素ノードのシーケンスと一致しない場合(特に、parent-xpath
が1つ以上の属性ノードまたはテキスト・ノードと一致する場合)、エラーが発生します。
child-xpath
(VARCHAR2
): 挿入されるchild-data
の直後の位置の既存の子を検索する相対XPath 1.0式。この式は、parent-xpath
に示された要素の子要素の名前を指定している必要があります。この式には、述語を含めることもできます。
child-data
(XMLType
): 挿入する子要素XMLデータ。このデータ型は常にXMLType
であり、要素ノードを含んでいます。child-data
内の最上位の要素ノードはそれぞれ、child-name
に示された要素と同じデータ型を持つ必要があります(そうでない場合、エラーが発生します)。
namespace
(オプション、VARCHAR2
): パラメータparent-xpath
、child-xpath
およびchild-data
の名前空間。
XMLデータchild-data
は、1つ以上の子要素として、parent-xpath
で見つかった各親要素の下に挿入されます。結果が戻されます。
NULL
引数に対する関数insertChildXMLbefore
の動作は、次のとおりです(優先順位の高い順に示します)。
child-name
がNULL
の場合、エラーが発生します。
target-data
またはparent-xpath
がNULL
の場合、NULL
が戻されます。
child-data
がNULL
の場合、挿入は行われません。target-data
がそのままの状態で戻されます。
図4-8に構文を示します。
SQL関数insertChildXMLafter
は、1つ以上のコレクション要素をターゲットの親要素の子として挿入します。各ターゲットは、指定された既存のコレクション要素の直後に挿入されます。挿入のターゲットである既存のXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力されたXMLType
インスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATE
を実行し、データベース・データを更新できます。
関数insertChildXMLafter
には、次のパラメータがあります(この順序どおり)。
target-data
(XMLType
): 挿入のターゲットであるXMLデータ。
parent-xpath
(VARCHAR2
): target-data
、child-data
内部の親要素を検索するXPath 1.0式が、各親要素の下に挿入されます。
parent-xpath
が要素ノードの空シーケンスと一致する場合、挿入は行われません。target-data
がそのままの状態で戻されます(エラーは発生しません)。parent-xpath
が要素ノードのシーケンスと一致しない場合(特に、parent-xpath
が1つ以上の属性ノードまたはテキスト・ノードと一致する場合)、エラーが発生します。
child-xpath
(VARCHAR2
): 挿入されるchild-data
の直前の位置の既存の子を検索する相対XPath 1.0式。この式は、parent-xpath
に示された要素の子要素の名前を指定している必要があります。この式には、述語を含めることもできます。
child-data
(XMLType
): 挿入する子要素XMLデータ。このデータ型は常にXMLType
であり、要素ノードを含んでいます。child-data
内の最上位の要素ノードはそれぞれ、child-name
に示された要素と同じデータ型を持つ必要があります(そうでない場合、エラーが発生します)。
namespace
(オプション、VARCHAR2
): パラメータparent-xpath
、child-xpath
およびchild-data
の名前空間。
XMLデータchild-data
は、1つ以上の子要素として、parent-xpath
で見つかった各親要素の下に挿入されます。結果が戻されます。
NULL
引数に対する関数insertChildXMLafter
の動作は、次のとおりです(優先順位の高い順に示します)。
child-name
がNULL
の場合、エラーが発生します。
target-data
またはparent-xpath
がNULL
の場合、NULL
が戻されます。
child-data
がNULL
の場合、挿入は行われません。target-data
がそのままの状態で戻されます。
図4-9に構文を示します。
SQL関数insertXMLbefore
は、任意の種類の1つ以上のノードを、属性ノード以外のターゲット・ノードの直前に挿入します。挿入のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力されたXMLType
インスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATE
を実行し、データベース・データを更新できます。
関数insertXMLbefore
には、次のパラメータがあります(この順序どおり)。
target-data
(XMLType
): 挿入のターゲットであるXMLデータ。
successor-xpath
(VARCHAR2
): 属性ノード以外の種類のtarget-data
内で0個以上のノードを検索するXPath 1.0式。XML-data
は、これらの各ノードの直前に挿入されます。つまり、XML-data
内のノードが、各successor-xpath
ノードの前の兄弟ノードになります。
successor-xpath
がノードの空のシーケンスと一致する場合、挿入は行われません。target-data
がそのままの状態で戻されます(エラーは発生しません)。successor-xpath
が、属性ノード以外のノードのシーケンスと一致する場合、エラーが発生します。
XML-data
(XMLType
): 挿入されるXMLデータ。任意の種類の1つ以上のノードです。ノードの順序は、挿入後も保持されます。
namespace
(オプション、VARCHAR2
): パラメータsuccessor-xpath
の名前空間。
XML-data
ノードは、successor-xpath
で見つかった属性以外のノードそれぞれの直前に挿入されます。結果が戻されます。
関数insertXMLbefore
のNULL
引数に対する動作は、次のとおりです。
target-data
またはparent-xpath
がNULL
の場合、NULL
が戻されます。
それ以外の場合、child-data
がNULL
であれば、挿入は行われません。target-data
がそのままの状態で戻されます。
図4-10に構文を示します。
例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.
SQL関数insertXMLafter
は、任意の種類の1つ以上のノードを、属性ノード以外のターゲット・ノードの直後に挿入します。挿入のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。この点ではinsertXMLbefore
に似ていますが、ターゲット・ノードの直前ではなく直後に挿入する点が異なります。
入力されたXMLType
インスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATE
を実行し、データベース・データを更新できます。
関数insertXMLafter
には、次のパラメータがあります(この順序どおり)。
target-data
(XMLType
): 挿入のターゲットであるXMLデータ。
successor-xpath
(VARCHAR2
): 属性ノード以外の種類のtarget-data
内で0個以上のノードを検索するXPath 1.0式。XML-data
は、これらの各ノードの直後に挿入されます。つまり、XML-data
内のノードが、各successor-xpath
ノードの後の兄弟ノードになります。
successor-xpath
がノードの空のシーケンスと一致する場合、挿入は行われません。target-data
がそのままの状態で戻されます(エラーは発生しません)。successor-xpath
が、属性ノード以外のノードのシーケンスと一致する場合、エラーが発生します。
XML-data
(XMLType
): 挿入されるXMLデータ。任意の種類の1つ以上のノードです。ノードの順序は、挿入後も保持されます。
namespace
(オプション、VARCHAR2
): パラメータsuccessor-xpath
の名前空間。
XML-data
ノードは、successor-xpath
で見つかった属性以外のノードそれぞれの直後に挿入されます。結果が戻されます。
関数insertXMLafter
のNULL
引数に対する動作は、次のとおりです。
target-data
またはparent-xpath
がNULL
の場合、NULL
が戻されます。
それ以外の場合、child-data
がNULL
であれば、挿入は行われません。target-data
がそのままの状態で戻されます。
図4-11に構文を示します。
SQL関数appendChildXML
は、任意の種類の1つ以上のノードを、指定された要素ノードの最後の子として挿入します。挿入のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力されたXMLType
インスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATE
を実行し、データベース・データを更新できます。
関数appendChildXML
には、次のパラメータがあります(この順序どおり)。
target-data
(XMLType
): ターゲットの親要素を含むXMLデータ。
parent-xpath
(VARCHAR2
): 挿入操作のターゲットであるtarget-data
内で0個以上の要素ノードを検索するXPath 1.0式。child-data
は、これらの各親要素の最後の子として挿入されます。
parent-xpath
が要素ノードの空シーケンスと一致する場合、挿入は行われません。target-data
がそのままの状態で戻されます(エラーは発生しません)。parent-xpath
が要素ノードのシーケンスと一致しない場合(特に、parent-xpath
が1つ以上の属性ノードまたはテキスト・ノードと一致する場合)、エラーが発生します。
child-data
(XMLType
): 挿入される子データ。任意の種類の1つ以上のノードです。ノードの順序は、挿入後も保持されます。
namespace
(オプション、VARCHAR2
): パラメータparent-xpath
の名前空間。
XMLデータchild-data
は、parent-xpath
により指定された各要素ノードの最後の子として挿入されます。結果が戻されます。
関数appendChildXML
のNULL
引数に対する動作は、次のとおりです。
target-data
またはparent-xpath
がNULL
の場合、NULL
が戻されます。
それ以外の場合、child-data
がNULL
であれば、挿入は行われません。target-data
がそのままの状態で戻されます。
図4-12に構文を示します。
例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.
SQL関数deleteXML
は、任意の種類のXMLノードを削除します。削除のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力されたXMLType
インスタンスのコピーが更新されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATE
を実行し、データベース・データを更新できます。
関数deleteXML
には、次のパラメータがあります(この順序どおり)。
target-data
(XMLType
): (削除される)ターゲット・ノードを含むXMLデータ。
xpath
(VARCHAR2
): 削除操作のターゲットであるtarget-data
内で0個以上のノードを検索するXPath 1.0式。これらのノードはすべて削除されます。
xpath
がノードの空シーケンスと一致する場合、削除は行われません。target-data
がそのままの状態で戻されます(エラーは発生しません)。xpath
が最上位の要素ノードと一致する場合、エラーが発生します。
namespace
(オプション、VARCHAR2
): パラメータxpath
の名前空間。
xpath
で見つかったXMLノードがtarget-data
から削除されます。結果が戻されます。target-data
またはxpath
がNULL
の場合、関数deleteXML
はNULL
を戻します。
図4-13に構文を示します。
例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.