2014-01-09 99 views
3

我有一些示例代碼如下:修改XML節點值 - 如updateXML相當於甲骨文12C

WITH xtbl AS 
     (SELECT 1 AS xtbl_id, 
       xmltype ('<node_root> 
         <node_1>12</node_1> 
         <node_2>233</node_2> 
         <node_3>223</node_3> 
         <node_4>234</node_4> 
        </node_root>') AS x 
      FROM Dual 
      UNION ALL 
      SELECT 2, xmltype ('<node_root> 
         <node_1></node_1> 
         <node_2>233</node_2> 
         <node_3>223</node_3> 
         <node_4>234</node_4> 
        </node_root>') 
      FROM Dual) 
SELECT xtbl_id, 
     x, 
     Updatexml (x, 
        '/node_root/node_2', 
        NULL, 
        '/node_root/node_3', 
        NULL, 
        '/node_root/node_4', 
        NULL) 
      AS xcol 
    FROM xtbl 
WHERE (SELECT node_1 
      FROM Xmltable ('node_root' 
         PASSING x 
         COLUMNS node_1 INTEGER PATH 'node_1')) 
      IS NOT NULL; 

我的要求是,每當/node_root/node_1x列不爲空,則替換值/node_root/node_2/node_root/node_3/node_root/node_4爲空。我在我的SELECT查詢中使用的Updatexml函數也一樣。

這裏的問題是Updatexml在Oracle 12c中不起作用。這就是我在子查詢中使用Xmltable的原因,它在過濾數據方面非常完美,但我無法用null替換節點值。

我試着在Oracle Docs看XQuery,但不明白它如何可以有助於取代節點值。

請提供一個描述性示例。

回答

2

Oracle文檔recommends to use XQuery to update XML。所以這是第一次嘗試。

首先,它可能與舊功能的方法。 XQuery的下面,可以用來代替調用XmlUpdate

XMLQuery(
     ' 
     declare function local:copy-replace($element as element()) { 
      if ($element/self::node_2) then <node_2/> 
      else if ($element/self::node_3) then <node_3/> 
      else if ($element/self::node_4) then <node_4/> 
      else element {node-name($element)} 
         {$element/@*, 
         for $child in $element/node() 
         return if ($child instance of element()) 
           then local:copy-replace($child) 
           else $child 
         } 
     }; 
     local:copy-replace($p/*) 
     ' 
     passing x as "p" returning content 
    ) as xcol_2 

另外,更短和更直觀的變體:

XMLQuery(
     '    
     copy $p2 := $p 
     modify(
      replace value of node $p2/node_root/node_2 with "", 
      replace value of node $p2/node_root/node_3 with "", 
      replace value of node $p2/node_root/node_4 with "" 
     ) 
     return $p2 
     ' 
     passing x as "p" returning content 
    ) as xcol_3 

,此外,它可能只返回如果沒有匹配的條件修改XML值:

WITH xtbl AS 
    (SELECT 1 AS xtbl_id, 
      xmltype ('<node_root> 
        <node_1>12</node_1> 
        <node_2>233</node_2> 
        <node_3>223</node_3> 
        <node_4>234</node_4> 
       </node_root>') AS x 
     FROM Dual 
     UNION ALL 
     SELECT 2, xmltype ('<node_root> 
        <node_1></node_1> 
        <node_2>233</node_2> 
        <node_3>223</node_3> 
        <node_4>234</node_4> 
       </node_root>') 
     FROM Dual) 
SELECT xtbl_id, 
    x, 
    XMLQuery(
     ' 
     for $test in $p/* 
     return 
      if(empty($p/node_root/node_1/text()))    
      then $p 
      else (
      copy $p2 := $p 
       modify(
       replace value of node $p2/node_root/node_2 with "", 
       replace value of node $p2/node_root/node_3 with "", 
       replace value of node $p2/node_root/node_4 with "" 
      ) 
       return $p2 
      ) 
     ' 
     passing x as "p" returning content 
    ) as xcol_4 
FROM xtbl 

所以有很多變種,以執行對XML值的操作,但這需要的XQuery更深入地瞭解nd XPath比一個相對簡單的XmlUpdate函數...

+0

第一個代碼示例工作在11gR2以及12c。第二個和第三個例子僅在12c工作。謝謝! – Rachcha

+0

這很奇怪,因爲我測試了所有針對11.2.0.3版Oracle的變體。你能否發佈你的Oracle的確切版本(例如'select * from v $ version')? – ThinkJet

+0

有兩個 - 11.2.0.1.0和12.1.0.1.0,都是64bit。 – Rachcha