更新节点的值,如果不存在则忽略

时间:2019-07-08 13:50:53

标签: oracle xmltype

我想替换XML中节点的值。 XML存储在Oracle 12.2数据库的XMLTYPE列中。 我的XML:

<Warehouse>
  <WarehouseId>1</WarehouseId>
  <WarehouseName>Southlake, Texas</WarehouseName>
  <Building>Owned</Building>
  <Area>25000</Area>
</Warehouse>

UPDATEXML函数可以完成任务,但是速度很慢。

select
UPDATEXML(myxmlcolumn, '/Warehouse/Building/text()','mynewvalue')
from mytable;

Oracle说UPDATEXML是deprecated,而应该使用XMLQUERY。 因此,我改用XMLQUERY:

select
 XMLQUERY(
'copy $t := $x modify(
  replace value of node $t/Warehouse/Building with "mynewvalue"
) return $t'
from mytable;

它的运行速度快得多,但是有一个小问题:如果所请求的节点不存在,它将失败并显示XVM-01155:[XUDY0027]目标表达式无效

例如,此选择失败,并出现上述错误(请注意ZZZ伪节点名称):

select
 XMLQUERY(
'copy $t := $x modify(
  replace value of node $t/Warehouse/ZZZ with "mynewvalue"
) return $t'
from mytable;

问题: 如何更改代码以忽略不存在的节点?

2 个答案:

答案 0 :(得分:1)

IF-ELSE声明可能会有所帮助:) 检查示例。

    with mytable as (select xmltype('<Warehouse>
      <WarehouseId>1</WarehouseId>
      <WarehouseName>Southlake, Texas</WarehouseName>
      <Building>Owned</Building>
      <Area>25000</Area>
    </Warehouse>') myxmlcolumn from dual) 
    select 

     XMLQUERY(
    'copy $t := . modify(
     if( $t/Warehouse/WarehouseName) then  
      (
        replace value of node $t/Warehouse/WarehouseName with "mynewvalue"
      )
      else ()
    ) return $t' passing myxmlcolumn returning content)

    from mytable
     union all 
     select 

     XMLQUERY(
    'copy $t := . modify(
     if( $t/Warehouse/ZZZZ) then  
      (
        replace value of node $t/Warehouse/ZZZZ with "mynewvalue"
      )
      else ()
    ) return $t' passing myxmlcolumn returning content)

    from mytable
union all
select 
 XMLQUERY(
'copy $t := . modify(
 for $node in  $t/Warehouse/ZZZZ
  return replace value of node $node with "mynewvalue"
) return $t' passing myxmlcolumn returning content) from mytable;

答案 1 :(得分:0)

按照@ArkadiuszŁukasiewicz的出色回答,我编写了完整的解决方案,其中包括:

  • 忽略不存在的节点
  • 在单个xmlquery调用中更改多个节点的能力

在这里:

select
    xmlquery(
'    copy $t := $x modify
        (
          (for $i in $t/Warehouse/Building
             return replace value of node $i with "aaa"),
          (for $i in $t/Warehouse/ZZZ
             return replace value of node $i with "bbb)
        )   
    return $t 
'
passing 
    XMLRECORD as "x"  
from mytable