2014-01-09 65 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