【问题标题】:How to update xml by filtering node in oracle?如何通过在 oracle 中过滤节点来更新 xml?
【发布时间】:2019-09-10 16:03:43
【问题描述】:

我在 xml 中有元素列表,如下所示

<Lists>
<Lists>
<list>
<Gender>Male</Gender>
<GenderCode>X</GenderCode>
</list>
<list>
<Gender>Female</Gender>
<GenderCode>X</GenderCode>
</list>
</Lists>

这里我需要根据 Gender 的值更新 GenderCode 值。假设如果 Gender 有“Male”,那么我需要将 GenderCode 更新为“M”。对于“女性”,它应该是“F”。有没有办法单独过滤男性列表并将男性列表的所有 GenderCode 更新为“M”,然后单独过滤女性并将 GenderCode 更新为“F”。有人可以在 oracle PL/SQL 或 Java 中提供建议吗?

【问题讨论】:

    标签: xml oracle sql-update


    【解决方案1】:

    您可以使用 XQuery 更新并将代码设置为完整值的第一个字符(假设这不是一个过度设计的示例);使用静态字符串:

    select xmlquery (
      'copy $n := $o
       modify (
         for $g in $n/Lists/list
         return replace value of node $g/GenderCode with fn:substring($g/Gender, 1, 1)
       )
       return $n'
      passing xmltype('<Lists>
    <list>
    <Gender>Male</Gender>
    <GenderCode>X</GenderCode>
    </list>
    <list>
    <Gender>Female</Gender>
    <GenderCode>X</GenderCode>
    </list>
    </Lists>') as "o"
      returning content)
    from dual;
    
    XMLQUERY('COPY$N:=$OMODIFY(FOR$GIN$N/LISTS/LISTRETURNREPLACEVALUEOFNODE$G/GENDER
    --------------------------------------------------------------------------------
    <Lists><list><Gender>Male</Gender><GenderCode>M</GenderCode></list><list><Gender
    >Female</Gender><GenderCode>F</GenderCode></list></Lists>
    

    或者可能更有用的是,将存储在表中的值更新为 XMLType:

    -- create and populate dummy table
    create table your_table (xml_column) as
    select xmltype('<Lists>
    <list>
    <Gender>Male</Gender>
    <GenderCode>X</GenderCode>
    </list>
    <list>
    <Gender>Female</Gender>
    <GenderCode>X</GenderCode>
    </list>
    </Lists>')
    from dual;
    
    update your_table
    set xml_column = xmlquery (
      'copy $n := $o
       modify (
         for $g in $n/Lists/list
         return replace value of node $g/GenderCode with fn:substring($g/Gender, 1, 1)
       )
       return $n'
      passing xml_column as "o"
      returning content
    );
    
    1 row updated.
    

    如果您的等效 xml_column 实际上存储为 varchar2 或 CLOB,那么只需将其包装起来:

      passing xmltype(xml_column) as "o"
    

    然后你可以看到值已经按照你想要的方式更新了:

    select xml_column from your_table;
    
    XML_COLUMN                                                                      
    --------------------------------------------------------------------------------
    <Lists>
      <list>
        <Gender>Male</Gender>
        <GenderCode>M</GenderCode>
      </list>
      <list>
        <Gender>Female</Gender>
        <GenderCode>F</GenderCode>
      </list>
    </Lists>
    

    如果需要从不同的表中查找代码,您可以使用fn:collection with oradb 从 XMLQuery 中访问表:

    -- undo previous update to go back to X codes
    rollback;
    
    -- look-up table
    create table genders (gender, gendercode) as
    select 'Male', 'M' from dual
    union all
    select 'Female', 'F' from dual;
    
    update your_table
    set xml_column = xmlquery (
      'copy $n := $o
       modify (
         for $g in $n/Lists/list, $c in fn:collection("oradb:/YOUR_SCHEMA/GENDERS")
           where $c/ROW/GENDER = $g/Gender
           return replace value of node $g/GenderCode with $c/ROW/GENDERCODE
       )
       return $n'
      passing xml_column as "o"
      returning content
    );
    
    1 row updated.
    

    得到相同的结果:

    select xml_column from your_table;
    
    XML_COLUMN                                                                      
    --------------------------------------------------------------------------------
    <Lists>
      <list>
        <Gender>Male</Gender>
        <GenderCode>M</GenderCode>
      </list>
      <list>
        <Gender>Female</Gender>
        <GenderCode>F</GenderCode>
      </list>
    </Lists>
    

    【讨论】:

    • 根据地区名称更新区号如何处理?我在其他一些表中有区域和区号映射。我需要进行更新,例如“区域 = Area1 然后 area_code = Area_Code1 的情况”。 Area1 XArea2 X
    • @gunaseelanthirumal - cmets 中的代码实际上不起作用,并且不清楚为什么您现在(部分)从性别转换为区号。我添加了一种在 XMLQuery 调用中从另一个表中查找数据的方法。以后请在您的问题中解释您真正在做什么,并包括所有相关信息,例如查找表的内容和代表性数据和预期结果。您的问题似乎与您实际尝试做的事情有很大不同。如果此编辑不能满足您的需要,请提出一个新问题,并提供所有需要的信息。
    猜你喜欢
    • 2013-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多