この章では、XMLアプリケーションに対するXMLType操作(XML Schemaに基づく、および基づかない)について説明します。XMLType列および表の作成、操作、更新および問合せのガイドラインが含まれます。
この章の内容は次のとおりです。
|
関連項目:
|
次の方法で、XMLType列からXMLデータを問い合せることができます。
SQL、PL/SQLまたはJavaでXMLType列を選択する方法。
XQuery言語を使用する方法。「XQueryのXMLTypeデータとの使用」を参照してください。
XMLQueryなどのSQL/XML関数を使用してXMLType列を直接問い合せる方法。
Oracle Text演算子を使用して全文検索を行う方法。第6章「XMLTypeデータの索引付け」および第12章「XMLデータの全文検索」を参照してください。
XPath言語はXML文書をナビゲートするためのW3C勧告です。XPath式もXQuery式だという意味で、XPath言語はXQuery言語のサブセットです。
XPathはXML文書をノードのツリーとしてモデル化します。このツリーを移動し、述語およびノード・テスト機能を適用するための豊富な操作が備わっています。XPath式をXML文書に適用すると、ノードのセットが戻されます。たとえば、式/PO/PONOは、文書のPOルート要素の下にあるすべてのPONO子要素を選択します。
|
注意: Oracle SQL関数およびXMLTypeメソッドは、W3C XPath勧告に準拠しています。このことは、XPath式がどのノードもターゲットにしていない場合にXMLデータに適用されると、空のシーケンスが戻される必要があることを示します。この場合にエラーが発生してはいけません。
XPath式をXMLデータに適用するOracle SQL関数または |
表4-1に、XPathで使用する共通構造体を示します。
| XPath構造体 | 説明 |
|---|---|
|
|
XPath式のツリーのルートを示します。たとえば、 |
|
|
任意のノードの子ノードを識別するための区切りとしても使用します。たとえば、 |
|
|
現行ノードのすべての子孫を識別するために使用します。たとえば、 |
|
|
任意の子ノードと一致させるためのワイルド・カードとして使用します。たとえば、 |
|
|
述語式を示すために使用します。XPathは 大カッコは、位置(索引)を示す場合にも使用します。たとえば、 |
|
関数 |
XPathおよびXQueryは、 |
XPathは単一のノードまたは一連の要素、テキストまたは属性ノードを識別する必要があります。XPathの結果はブール式にはできません。
XMLTypeデータは、PL/SQL、CまたはJavaを使用して選択できます。XMLTypeメソッドgetNumberVal()を使用して、XMLデータをNUMBERとして取り出すこともできます。
SQL/XML標準関数XMLQuery、XMLTable、XMLExistsおよびXMLCastを使用すると、XMLTypeデータを問い合せて一部を抽出できます。
XMLQuery関数およびXMLTable関数の詳細は、第5章「Oracle XML DBでのXQueryの使用」を参照してください。関数XMLExistsおよびXMLCastについては、この項で説明します。
図4-1に、SQL/XMLの標準関数XMLExistsの構文を示します。この関数は、所定のXQuery式が空でないXQueryシーケンスを戻すかどうかを確認します。その場合、関数はTRUEを戻します。そうでない場合はFALSEを戻します。
XML_passing_clause::=

XQuery_stringは完結したXQuery式で、プロローグをリテラル文字列として含む場合があります。XQueryのPASSING句(構文図のXML_passing_clause)を使用してバインドするXQuery変数を含めることができます。SQL/XML関数XMLQueryに対し認識されている、事前定義された名前空間の接頭辞は、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句は暗黙的で、省略可能です。
/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-1では、SQL/XML標準関数XMLExistsを使用して、SpecialInstructionsがExpediteに設定されている行を選択します。
例4-1 SQL/XML関数XMLExistsを使用したノードの検索
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/XML関数XMLExistsを使用してファンクション索引を作成すると、実行を高速化できます。また、XMLIndex索引を作成して、任意のXQuery検索を高速化することもできます。
|
注意: Oracle Database 11gリリース2以前では、一部のユーザーは一部の処理の実行にOracle SQL関数existsNodeを使用していました。これらの処理は、SQL/XML関数XMLExistsを使用してより効率的に実行できるようになっています。関数existsNodeは、Oracle Database 11gリリース2で非推奨になりました。2つの関数は、次の重要な点が異なります。
|
図4-2に、SQL/XMLの標準関数XMLCastの構文を示します。
SQL/XML標準関数XMLCastは、その最初の引数を2番目の引数で指定されるSQLスカラー・データ型にキャストします。最初の引数は、評価されるSQL式です。次のSQLデータ型は第2引数として使用できます。
NUMBER
VARCHAR2
CHAR
CLOB
BLOB
REF XMLTYPE
任意のSQL日時データ型
|
注意: 標準SQL/XMLとは異なり、Oracle XML DBではXMLをSQLスカラー・データ型にキャストするためのXMLCastの使用を制限しています。Oracle XML DBは、XMLからXMLへのキャストやスカラーSQL型からXMLへのキャストをサポートしていません。 |
最初のXMLCast引数の評価結果は、XML値になります。この値は、XQueryアトミック処理を使用して、XQueryアトミック値をターゲット・データ型にキャストすることにより、ターゲットSQLデータ型に変換されます。この変換に失敗すると、エラーが発生します。変換が成功すると、戻される結果は、ターゲット・データ型のインスタンスになります。
例4-2の問合せは、Referenceノードのスカラー値を抽出します。
例4-2 XMLCASTを使用したXMLフラグメントのスカラー値の抽出
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を使用してXMLデータを問い合せる方法を示します。例4-3では、purchaseorder表に2行を挿入してから、SQL/XML関数XMLCast、XMLQueryおよびXMLExistsを使用してそれらの行のデータを問い合せます。
例4-3 XMLTYPEデータの問合せ
INSERT INTO purchaseorder
VALUES (XMLType(bfilename('XMLDIR', 'SMCCAIN-2002091213000000PDT.xml'),
nls_charset_id('AL32UTF8')));
INSERT INTO purchaseorder
VALUES (XMLType(bfilename('XMLDIR', 'VJONES-20020916140000000PDT.xml'),
nls_charset_id('AL32UTF8')));
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30)) reference,
XMLCast(XMLQuery('$p/PurchaseOrder/*//User'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30)) userid,
CASE
WHEN XMLExists('$p/PurchaseOrder/Reject/Date'
PASSING po.OBJECT_VALUE AS "p")
THEN 'Rejected'
ELSE 'Accepted'
END "STATUS",
XMLCast(XMLQuery('$p//Date'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(12)) status_date
FROM purchaseorder po
WHERE XMLExists('$p//Date' PASSING po.OBJECT_VALUE AS "p")
ORDER BY XMLCast(XMLQuery('$p//Date' PASSING po.OBJECT_VALUE AS "p"
RETURNING CONTENT)
AS VARCHAR2(12));
REFERENCE USERID STATUS STATUS_DATE
-------------------------------- -------- -------- ------------
VJONES-20020916140000000PDT SVOLLMAN Accepted 2002-10-11
SMCCAIN-2002091213000000PDT SKING Rejected 2002-10-12
2 rows selected.
例4-4では、PL/SQLカーソルを使用してXMLデータを問い合せます。ローカルのXMLTypeインスタンスを使用して、一時データが格納されます。
例4-4 PL/SQLカーソルを使用した一時XMLTYPEデータの問合せ
DECLARE
xNode XMLType;
vText VARCHAR2(256);
vReference VARCHAR2(32);
CURSOR getPurchaseOrder(reference IN VARCHAR2) IS
SELECT OBJECT_VALUE XML
FROM purchaseorder
WHERE XMLExists('$p/PurchaseOrder[Reference=$r]'
PASSING OBJECT_VALUE AS "p",
reference AS "r");
BEGIN
vReference := 'EABEL-20021009123335791PDT';
FOR c IN getPurchaseOrder(vReference) LOOP
xNode := c.XML.extract('//Requestor');
SELECT XMLSerialize(CONTENT
XMLQuery('//text()' PASSING xNode RETURNING CONTENT))
INTO vText FROM DUAL;
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');
SELECT XMLSerialize(CONTENT
XMLQuery('//text()' PASSING xNode RETURNING CONTENT))
INTO vText FROM DUAL;
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-5では、SQL/XML関数XMLTableを使用して、XML発注書からデータを抽出し、そのデータをリレーショナル表に挿入します。
例4-5 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 'Reject/User',
daterejected DATE PATH 'Reject/Date',
comments VARCHAR2(2048) PATH 'Reject/Comments',
specialinstructions VARCHAR2(2048) PATH 'SpecialInstructions') t
WHERE t.reference = 'EABEL-20021009123336251PDT';
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';
SELECT reference, userid, shiptoname, specialinstructions FROM purchaseorder_table;
REFERENCE USERID SHIPTONAME SPECIALINSTRUCTIONS
-------------------------------- -------- ------------------------------------------------ -------------------
EABEL-20021009123336251PDT EABEL Ellen S. Abel Counter to Counter
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
例4-6では、PL/SQLプロシージャを定義および使用して、XML発注書からデータを抽出し、そのデータをリレーショナル表に挿入します。
例4-6 PL/SQLプロシージャを使用したXMLデータの抽出および表への挿入
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)
SELECT * FROM XMLTable('$p/PurchaseOrder' PASSING purchaseorder AS "p"
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 'Reject/User',
daterejected DATE PATH 'Reject/Date',
comments VARCHAR2(2048) PATH 'Reject/Comments',
specialinstructions VARCHAR2(2048) PATH 'SpecialInstructions');
INSERT INTO purchaseorder_lineitem (reference, lineno, upc, description, quantity, unitprice)
SELECT t.reference, li.lineno, li.upc, li.description, li.quantity, li.unitprice
FROM XMLTable('$p/PurchaseOrder' PASSING purchaseorder AS "p"
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;
END;
CALL insertPurchaseOrder(XMLType(bfilename('XMLDIR', 'purchaseOrder.xml'), nls_charset_id('AL32UTF8')));
SELECT reference, userid, shiptoname, specialinstructions FROM purchaseorder_table;
REFERENCE USERID SHIPTONAME SPECIALINSTRUCTIONS
-------------------------------- -------- ------------------------------------------------ -------------------
SBELL-2002100912333601PDT SBELL Sarah J. Bell Air Mail
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
例4-7では、顧客名に"ll"(Lが2個)が付き、出荷指示に"Shores"という語が含まれている発注書のXML要素PurchaseOrderから発注書名を抽出します。この例では、Oracle XQuery拡張関数ora:containsを使用して全文検索を実行します。
例4-7 SQL/XML関数を使用したXMLデータの検索
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Requestor' PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT) AS VARCHAR2(128)) name, count(*) FROM purchaseorder po WHERE XMLExists( 'declare namespace ora="http://xmlns.oracle.com/xdb"; (: :) $p/PurchaseOrder/ShippingInstructions[ora:contains(address/text(), "Shores") > 0]' PASSING po.OBJECT_VALUE AS "p") AND XMLCast(XMLQuery('$p/PurchaseOrder/Requestor/text()' PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT) AS VARCHAR2(128)) LIKE '%ll%' GROUP BY XMLCast(XMLQuery('$p/PurchaseOrder/Requestor' PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT) AS VARCHAR2(128)); NAME COUNT(*) -------------------- ---------- Allan D. McEwen 9 Ellen S. Abel 4 Sarah J. Bell 13 William M. Smith 7
例4-8は、SQL/XML関数XMLQueryを使用して、XPath式によって識別されるノードを抽出する方法を示しています。XMLQueryにより戻されるXMLTypeインスタンスは、ノードの集合、単一のノードまたはテキスト値のいずれかになります。例4-8では、XMLTypeメソッドisFragment()を使用して、結果がフラグメントかどうかを判別します。
例4-8 XMLQUERYを使用したXMLTYPEインスタンスからのフラグメントの抽出
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference' PASSING po.OBJECT_VALUE AS "p"
RETURNING CONTENT)
AS VARCHAR2(30)) reference,
count(*)
FROM purchaseorder po, XMLTable('$p//LineItem[Part/@Id="37429148327"]' PASSING OBJECT_VALUE AS "p")
WHERE XMLQuery('$p/PurchaseOrder/LineItems/LineItem[Part/@Id="37429148327"]'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT).isFragment() = 1
GROUP BY XMLCast(XMLQuery('$p/PurchaseOrder/Reference' PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30))
ORDER BY XMLCast(XMLQuery('$p/PurchaseOrder/Reference' PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30));
REFERENCE COUNT(*)
-------------------------------- ----------
TFOX-20021009123337784PDT 3
|
注意: フラグメントはXMLType列に挿入できません。SQL関数sys_XMLGenを使用すると、囲みタグを追加することによってフラグメントを整形式の文書に変換できます。「SYS_XMLGEN Oracle SQL関数」を参照してください。 |
この項では、一時データおよび表に格納されたデータの両方の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-9では、SQL UPDATE文を使用してXMLTypeインスタンスを更新します。
例4-9 SQL UPDATE文を使用したXMLTypeデータの更新
SELECT t.reference, li.lineno, li.description
FROM purchaseorder po,
XMLTable('$p/PurchaseOrder' PASSING po.OBJECT_VALUE AS "p"
COLUMNS reference VARCHAR2(28) PATH 'Reference',
lineitem XMLType PATH 'LineItems/LineItem') t,
XMLTable('$l/LineItem' PASSING t.lineitem AS "l"
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
UPDATE purchaseorder po
SET po.OBJECT_VALUE = XMLType(bfilename('XMLDIR','NEW-DAUSTIN-20021009123335811PDT.xml'),
nls_charset_id('AL32UTF8'))
WHERE XMLExists('$p/PurchaseOrder[Reference="DAUSTIN-20021009123335811PDT"]'
PASSING po.OBJECT_VALUE AS "p");
SELECT t.reference, li.lineno, li.description
FROM purchaseorder po,
XMLTable('$p/PurchaseOrder' PASSING po.OBJECT_VALUE AS "p"
COLUMNS reference VARCHAR2(28) PATH 'Reference',
lineitem XMLType PATH 'LineItems/LineItem') t,
XMLTable('$l/LineItem' PASSING t.lineitem AS "l"
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
XMLデータを付加的に更新する(周囲のXML文書全部を置き換えずにXMLデータを置換、挿入または削除する)ために使用できるOracle SQL関数がいくつかあります。これは、部分更新とも呼ばれます。これらのOracle 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関数」を参照してください。
関数insertChildXML、insertChildXMLbefore、insertChildXMLafter、insertXMLbefore、insertXMLafter、appendChildXMLを使用して、XMLデータを挿入します。関数deleteXMLを使用して、XMLデータを削除します。XMLデータを置換するには、関数updateXMLを使用します。
特に、親ノード全体を置き換えることによってXMLデータを挿入または削除する場合は、関数updateXMLを使用しないでください。使用しても機能しますが、これ以外のいずれかの関数を使用するほうがローカルな更新を実行できるため、効率的です。
これらのOracle SQL関数はそれ自体ではデータベース・データを変更しません。これらはすべて副次的な影響のない純粋な関数です。各関数は、入力されたXMLデータにXPath式の引数を適用し、入力されたXMLデータの変更済コピーを戻します。その後、その結果を使用してSQL DML演算子UPDATEを実行し、データベース・データを変更できます。これは、SQL関数upperを使用してデータベース・データを大文字に変換する方法と変わりません。UPDATEなどのSQL DML演算子を使用して、格納されたデータを変更する必要があります。
これらの関数はそれぞれ、XML Schemaに基づくXML文書および基づかないXML文書のどちらにも使用できます。XML Schemaに基づくデータの場合、これらのOracle SQL関数はその結果に対して部分検証を実行します。該当する場合は、引数の値のXML Schemaとの互換性もチェックされます。
|
注意: Oracle SQL関数およびXMLTypeメソッドは、W3C XPath勧告に準拠しています。このことは、XPath式がどのノードもターゲットにしていない場合にXMLデータに適用されると、空のシーケンスが戻される必要があることを示します。この場合にエラーが発生してはいけません。
XPath式をXMLデータに適用するOracle SQL関数または |
XMLノードを既存のXMLデータ(のコピー)に挿入するためのOracle 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操作のために最適化されている点が異なります。
Oracle 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名前空間。
Oracle SQL関数updateXMLを使用すると、既存の要素、属性およびノードを新しい値で置換できます。新しいノードを挿入したり、既存のノードを削除することは、効率的な方法ではありません。updateXMLを使用して、挿入または削除するノードの親ノード全体を置換するだけで、挿入および削除を実行できます。
関数updateXMLは、メモリー内の一時XMLインスタンスのみを更新します。表に格納されたデータを更新するには、SQLのUPDATE文を使用します。
図4-3に構文を示します。
例4-10では、新しいXML文書を作成するのではなく、UPDATE文の右側にupdateXMLを使用して表内のXML文書を更新します。選択された部分のみではなく、文書全体が更新されます。
例4-10 UPDATEおよびUPDATEXMLを使用したXMLTYPEの更新
SELECT XMLQuery('$p/PurchaseOrder/Actions/Action[1]' PASSING po.OBJECT_VALUE AS "p"
RETURNING CONTENT) action
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
ACTION
--------------------------------
<Action>
<User>SVOLLMAN</User>
</Action>
UPDATE purchaseorder po
SET po.OBJECT_VALUE = updateXML(po.OBJECT_VALUE,
'/PurchaseOrder/Actions/Action[1]/User/text()',
'SKING')
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
SELECT XMLQuery('$p/PurchaseOrder/Actions/Action[1]' PASSING po.OBJECT_VALUE AS "p"
RETURNING CONTENT) action
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
ACTION
---------------------------------
<Action>
<User>SKING</User>
</Action>
例4-11では、Oracle SQL関数updateXMLを使用して複数のノードを更新します。
例4-11 UPDATEXMLを使用した、複数のテキスト・ノードと属性値の更新
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Requestor'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30)) name,
XMLQuery('$p/PurchaseOrder/LineItems'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT) lineitems
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
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>
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 XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Requestor'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30)) name,
XMLQuery('$p/PurchaseOrder/LineItems'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT) lineitems
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
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>
例4-12では、SQL関数updateXMLを使用して、コレクション内で選択されたノードを更新します。
例4-12 UPDATEXMLを使用した、コレクション内で選択されたノードの更新
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Requestor'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30)) name,
XMLQuery('$p/PurchaseOrder/LineItems'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT) lineitems
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
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>
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 XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Requestor'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30)) name,
XMLQuery('$p/PurchaseOrder/LineItems'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT) lineitems
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
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>
XML要素をNULLに更新すると、要素の属性および子が削除され、要素は空になります。要素のタイプおよび名前空間プロパティは保持されます。例4-13を参照してください。
属性値をNULLに更新した場合、値は空の文字列として表示されます。例4-13を参照してください。
要素のテキスト・ノードをNULLに更新すると、その要素のコンテンツ(テキスト)は削除されます。要素自体は残りますが、空になります。 例4-14を参照してください。
例4-13では、次のものすべてをNULLに更新します。
Description要素と、Part要素の属性Id値が715515009058のLineItem要素のQuantity属性
Description要素のコンテンツ(テキスト)が「The Unbearable Lightness Of Being」であるLineItem要素
例4-13 UPDATEXMLを使用したNULL更新 - 要素および属性
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Requestor'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30)) name,
XMLQuery('$p/PurchaseOrder/LineItems'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT) lineitems
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
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>
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 XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Requestor'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30)) name,
XMLQuery('$p/PurchaseOrder/LineItems'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT) lineitems
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
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>
例4-14では、Description属性の値が「A Night to Remember」であるPart要素のテキスト・ノードをNULLに更新します。この例のXMLデータは、修正された別の発注書XML Schemaに対応しています(「コピーに基づく拡張の使用例」を参照)。そのXML Schemaでは、DescriptionはPart要素の属性であり、兄弟要素ではありません。
例4-14 UPDATEXMLを使用したNULL更新 - テキスト・ノード
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/LineItems/LineItem/Part[@Description="A Night to Remember"]'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(128)) part
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[@Reference="SBELL-2003030912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
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 XMLExists('$p/PurchaseOrder[@Reference="SBELL-2003030912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/LineItems/LineItem/Part[@Description="A Night to Remember"]'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(128)) part
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[@Reference="SBELL-2003030912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
PART
----
<Part Description="A Night to Remember" UnitCost="39.95"/>
同じXMLノードをupdateXML式で複数回更新できます。たとえば、/EMP[EMPNO=217]および/EMP[EMPNAME="Jane"]/EMPNOの両方を更新できます。ここで最初のXPathはそれを含むEMPNOノードも識別します。更新の順番は、左から右へ、XPath式の順番によって決定されます。連続するXPathはそれぞれ、前のXPathの更新結果に基づいて機能します。
ここでは、Oracle SQL関数updateXMLを使用する際にDOM再現性を保持するためのガイドラインを示します。
要素をNULLに更新する場合は、<myElem/>のように、その親で目的の要素が空に表示されるようにします。要素内のテキスト・ノードをNULLに更新する場合は、その要素からテキスト・ノードを削除します。属性ノードをNULLに更新する場合は、myAttr=""のように、属性の値が空の文字列になるようにします。
complexType要素をNULLに更新する場合は、<myElem/>のように、その親で目的の要素が空に表示されるようにします。SQLインラインsimpleType要素をNULLに更新する場合は、その親から要素が見えないようにします。テキスト・ノードをNULLに更新する場合は、親simpleType要素をNULLに設定する場合と同じ手順を実行します。複合コンテンツを格納する位置指定ディスクリプタがないため、DOM再現性が保持されない場合、テキスト・ノードはsimpleType要素内でのみ出現できます。属性ノードをNULLに更新する場合は、要素からその属性を削除します。
ほとんどの場合、XMLデータを更新するOracle SQL関数は、入力されたXML文書全体のコピーをメモリー内に生成してから、そのコピーを更新します。ただし、関数updateXML、insertChildXML、insertChildXMLbefore、insertChildXMLafterおよびdeleteXML 、つまり、insertXMLbefore、insertXMLafterおよびappendChildXMLを除くすべてが、オブジェクト・リレーショナル形式またはバイナリXMLとして格納されている、XMLType表および列に対するSQL UPDATE操作のために最適化されます。
構造化記憶域の場合、特定の条件が満たされると、関数呼び出しは、オブジェクト・リレーショナル列を新しい値で直接更新するようにリライトできます。バイナリXML記憶域の場合、ターゲットの更新の前のデータは変更されず、SecureFile LOBが使用されている場合(デフォルトの動作)は、スライド挿入を使用して、変更が必要なデータ部分のみが更新されます。
|
関連項目:
|
オブジェクト・リレーショナル記憶域の例では、例4-15に記載されているupdateXMLへのXPath引数は、Oracle XML DBで処理され、例4-16に記載されている同等のオブジェクト・リレーショナルSQLコードにリライトされます。
例4-15 UPDATEXML式内のXPath式
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/User'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30))
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLCAST(XMLQUERY('$P/PURCHASEO
------------------------------
SBELL
UPDATE purchaseorder
SET OBJECT_VALUE = updateXML(OBJECT_VALUE, '/PurchaseOrder/User/text()', 'SVOLLMAN')
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/User'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30))
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLCAST(XMLQUERY('$P/PURCHASEO
------------------------------
SVOLLMAN
例4-16 UPDATEXML式と同等のオブジェクト・リレーショナル形式の文
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/User'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30))
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLCAST(XMLQUERY('$P/PURCHASEO
------------------------------
SBELL
UPDATE purchaseorder p
SET p."XMLDATA"."USERID" = 'SVOLLMAN'
WHERE p."XMLDATA"."REFERENCE" = 'SBELL-2002100912333601PDT';
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/User'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30))
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLCAST(XMLQUERY('$P/PURCHASEO
------------------------------
SVOLLMAN
|
注意: ここで説明するDML用のXMLDATAの使用方法は、Oracle XML DBの内部動作の説明に限定されます。DML操作には、XMLDATA自身を使用しないでください。XMLDATAを直接使用できるのは、DDL操作に対してのみで、DML操作には使用できません。
一般的に、コード内ではXML Schemaオブジェクト・モデルとSQLオブジェクト・モデル間の現在のマッピングに依存しないでください。Oracle XML DB実装のマッピングは将来変更される可能性があります。 |
XMLデータを変更するOracle SQL関数(updateXML、insertChildXML、insertChildXMLbefore、insertChildXMLafter、insertXMLbefore、insertXMLafter、appendChildXMLおよびdeleteXML)を使用して、XMLデータの新しいビューを作成できます。
例4-17では、Oracle SQL関数updateXMLを使用してpurchaseorder表のビューを作成します。
例4-17 UPDATEXMLを使用したビューの作成
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;
SELECT OBJECT_VALUE FROM purchaseorder_summary
WHERE XMLExists('$p/PurchaseOrder[Reference="DAUSTIN-20021009123335811PDT"]' PASSING OBJECT_VALUE AS "p");
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>
Oracle SQL関数insertChildXMLは、親のXML要素の下に新しい子(同じ型の1つ以上の要素、または単一の属性)を挿入します。挿入のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力XMLTypeインスタンスのコピーが変更されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。
関数insertChildXMLには、次のパラメータがあります(この順序どおり)。
target-data(XMLType) - ターゲットの親要素を含むXMLデータ。
parent-xpath(VARCHAR2)– target-data内で親要素を検索するXPath 1.0式。child-dataは、それぞれの親要素の下に挿入されます。
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-4に構文を示します。
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という名前の子要素になるように挿入されます。ただし、子シーケンス内の位置は予想外の結果になります。
既存の空でない子要素のコレクションに要素を挿入する必要があり、順序が重要な場合は、SQL/XML関数appendChildXMLまたはinsertXMLbeforeを使用してください。
例4-18に、SQL UPDATE文とOracle SQL関数insertChildXMLを使用して、新しいLineItem要素をLineItems要素の子として挿入する方法を示します。
例4-18 LineItems要素へのLineItem要素の挿入
SELECT XMLQuery('$p/PurchaseOrder/LineItems/LineItem[@ItemNumber=222]'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLQUERY('$P/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 XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING OBJECT_VALUE AS "p");
SELECT XMLQuery('$p/PurchaseOrder/LineItems/LineItem[@ItemNumber=222]'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLQUERY('$P/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スキーマに基づいていて、ネームスペースを参照する場合、挿入するデータも同じネームスペースを参照する必要があります。参照しない場合は、挿入されるデータがXMLスキーマに準拠しないため、エラーが発生します。
例4-19は例4-18と似ていますが、挿入されるLineItem要素が名前空間を参照しています。これは、関連するXML Schemaでこの要素に対する名前空間が必要であることを前提としています。
例4-19 名前空間を使用する要素の挿入
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 XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING OBJECT_VALUE AS "p");
このような名前空間の使用方法は、関数insertChildXMLに対する名前空間引数の使用方法とは異なるため、注意してください。そのオプションの引数に指定される名前空間は、挿入されるコンテンツではなく、XPath引数のみに適用されます。
Oracle SQL関数insertChildXMLbeforeは、1つ以上のコレクション要素をターゲットの親要素の子として挿入します。各ターゲットは、指定された既存のコレクション要素の直前に挿入されます。挿入のターゲットである既存のXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力XMLTypeインスタンスのコピーが変更されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。
関数insertChildXMLbeforeには、次のパラメータがあります(この順序どおり)。
target-data(XMLType) - 挿入のターゲットであるXMLデータ。
parent-xpath(VARCHAR2)– target-data内で親要素を検索するXPath 1.0式。child-dataは、それぞれの親要素の下に挿入されます。
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-xpathに示された要素と同じデータ型を持つ必要があります(そうでない場合、エラーが発生します)。
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-5に構文を示します。
Oracle SQL関数insertChildXMLafterは、1つ以上のコレクション要素をターゲットの親要素の子として挿入します。各ターゲットは、指定された既存のコレクション要素の直後に挿入されます。挿入のターゲットである既存のXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力XMLTypeインスタンスのコピーが変更されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。
関数insertChildXMLafterには、次のパラメータがあります(この順序どおり)。
target-data(XMLType) - 挿入のターゲットであるXMLデータ。
parent-xpath(VARCHAR2)– target-data内で親要素を検索するXPath 1.0式。child-dataは、それぞれの親要素の下に挿入されます。
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-xpathに示された要素と同じデータ型を持つ必要があります(そうでない場合、エラーが発生します)。
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-6に構文を示します。
Oracle 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-7に構文を示します。
例4-20 最初のLineItem要素の直前にLineItem要素を挿入
SELECT XMLQuery('$p/PurchaseOrder/LineItems/LineItem[1]'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLQUERY('$P/PURCHASEORDER/LINEITEMS/LINEITEM[1]'PASSINGPO.OBJECT_
------------------------------------------------------------------
<LineItem ItemNumber="1">
<Description>Salesman</Description>
<Part Id="37429158920" UnitPrice="39.95" Quantity="2"/>
</LineItem>
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 XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING OBJECT_VALUE AS "p");
SELECT XMLQuery('$p/PurchaseOrder/LineItems/LineItem[position() <= 2]'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLQUERY('$P/PURCHASEORDER/LINEITEMS/LINEITEM[POSITION()<=2]'PASSINGPO.OBJECT_
------------------------------------------------------------------------------
<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>
|
注意: Oracle SQL関数insertXMLbeforeを使用する問合せは、最適化されません。このため、関数insertChildXML、insertChildXMLbeforeまたはinsertChildXMLafterをかわりに使用することをお薦めします。「XQuery用のパフォーマンス・チューニング」を参照してください。 |
Oracle 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-8に構文を示します。
|
注意: Oracle SQL関数insertXMLafterを使用する問合せは、最適化されません。このため、関数insertChildXML、insertChildXMLbeforeまたはinsertChildXMLafterをかわりに使用することをお薦めします。「XQuery用のパフォーマンス・チューニング」を参照してください。 |
Oracle SQL関数appendChildXMLは、任意の種類の1つ以上のノードを、指定された要素ノードの最後の子として挿入します。挿入のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力XMLTypeインスタンスのコピーが変更されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。
関数appendChildXMLには、次のパラメータがあります(この順序どおり)。
target-data(XMLType): ターゲットの親要素を含むXMLデータ。
parent-xpath(VARCHAR2) - 挿入操作のターゲットであるtarget-dataにあるゼロまたは複数の要素ノードを検索する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-9に構文を示します。
例4-21 Action要素の最後の子としてDate要素を挿入
SELECT XMLQuery('$p/PurchaseOrder/Actions/Action[1]'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLQUERY('$P/PURCHASEORDER/ACTIONS/ACTION[1]'PASSINGPO.OBJECT_VALUE
-------------------------------------------------------------------
<Action>
<User>KPARTNER</User>
</Action>
UPDATE purchaseorder
SET OBJECT_VALUE =
appendChildXML(OBJECT_VALUE,
'PurchaseOrder/Actions/Action[1]',
XMLType('<Date>2002-11-04</Date>'))
WHERE XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING OBJECT_VALUE AS "p");
SELECT XMLQuery('$p/PurchaseOrder/Actions/Action[1]'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLQUERY('$P/PURCHASEORDER/ACTIONS/ACTION[1]'PASSINGPO.OBJECT_VALUE
-------------------------------------------------------------------
<Action>
<User>KPARTNER</User>
<Date>2002-11-04</Date>
</Action>
|
注意: Oracle SQL関数appendChildXMLを使用する問合せは、最適化されません。このため、関数insertChildXML、insertChildXMLbeforeまたはinsertChildXMLafterをかわりに使用することをお薦めします。「XQuery用のパフォーマンス・チューニング」を参照してください。 |
Oracle SQL関数deleteXMLは、任意の種類のXMLノードを削除します。削除のターゲットであるXML文書は、XML Schemaに基づく文書でも、XML Schemaに基づかない文書でもかまいません。
入力XMLTypeインスタンスのコピーが変更されて戻されます。元のデータは影響を受けません。その戻されたデータを使用してSQL操作UPDATEを実行し、データベース・データを更新できます。
関数deleteXMLには、次のパラメータがあります(この順序どおり)。
target-data(XMLType) - (削除される)ターゲット・ノードを含むXMLデータ。
xpath(VARCHAR2) - 削除操作のターゲットであるtarget-dataにあるゼロまたは複数のノードを検索するXPath 1.0式。こうした各ノードは削除されます。
xpathがノードの空シーケンスと一致する場合、削除は行われず、target-dataがそのままの状態で戻されます(エラーは発生しません)。xpathが最上位の要素ノードと一致する場合、エラーが発生します。
namespace(オプション、VARCHAR2) : パラメータxpathの名前空間。
xpathで見つかったXMLノードがtarget-dataから削除されます。target-dataまたはxpathがNULLの場合、関数deleteXMLはNULLを戻します。
図4-10に構文を示します。
例4-22 LineItem要素(番号222)の削除
SELECT XMLQuery('$p/PurchaseOrder/LineItems/LineItem[@ItemNumber=222]'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLQUERY('$P/PURCHASEORDER/LINEITEMS/LINEITEM[@ITEMNUMBER=222]'PASSINGPO
------------------------------------------------------------------------
<LineItem ItemNumber="222">
<Description>The Harder They Come</Description>
<Part Id="953562951413" UnitPrice="22.95" Quantity="1"/>
</LineItem>
UPDATE purchaseorder
SET OBJECT_VALUE =
deleteXML(OBJECT_VALUE,
'/PurchaseOrder/LineItems/LineItem[@ItemNumber="222"]')
WHERE XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING OBJECT_VALUE AS "p");
SELECT XMLQuery('$p/PurchaseOrder/LineItems/LineItem[@ItemNumber=222]'
PASSING po.OBJECT_VALUE AS "p" RETURNING CONTENT)
FROM purchaseorder po
WHERE XMLExists('$p/PurchaseOrder[Reference="AMCEWEN-20021009123336171PDT"]'
PASSING po.OBJECT_VALUE AS "p");
XMLQUERY('$P/PURCHASEORDER/LINEITEMS/LINEITEM[@ITEMNUMBER=222]'PASSINGPO
------------------------------------------------------------------------
1 row selected.