sql - 修改 XML 节点值 - Oracle 12c 的 UpdateXML 等价物

标签 sql xml oracle xquery oracle12c

我有一些示例代码如下:

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;

我的要求是,每当 x 列中的 /node_root/node_1 不为空时,替换 /node_root/node_2 的值,/node_root/node_3/node_root/node_4 为空。我在 SELECT 查询中使用的 Updatexml 函数执行相同的操作。

这里的问题是 Updatexml 在 Oracle 12c 中不起作用。这就是为什么我在子查询中使用了 Xmltable 并且它在过滤数据方面工作得很好,但我无法用 null 替换节点值。

我试着查看 Oracle Docs用于 XQuery,但无法理解它如何有助于替换节点值。

请提供一个描述性示例。

最佳答案

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值进行操作,但这需要更深入的了解XQueryXPath而不是相对简单的 XmlUpdate 函数...

关于sql - 修改 XML 节点值 - Oracle 12c 的 UpdateXML 等价物,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21016083/

相关文章:

sql - 在 MySQL 中更改列数据类型时如何保留数据?

xml:如何缩进子元素但将属性保留在新行上

sql - 在 Rails 应用程序中集成 Oracle 数据库

sql - 在 SQL 和查询中将日期转换为日期时间大于

MySQL:我的教授想要一个没有主键的表

mysql - SQL读取网格矩阵

java - 在 Java 中读取 Xml Formatter 格式的日志文件的最佳策略?

java - 将 XML 字符串发送到 Jersey 中的 Web 服务

sql - 图问题: connect by NOCYCLE prior replacement in SQL server?

oracle - 加快 Oracle Text 索引或让索引器仅在低加载时间下工作