【问题标题】:Extract specific xml node from duplicate ones in oracle从 oracle 中的重复节点中提取特定的 xml 节点
【发布时间】:2017-05-24 23:14:19
【问题描述】:

给出的是“XYZ”表中“my_xml”列的值

<?xml version="1.0" encoding="UTF-8"?>
<India>
  <city>
    <string>ADI</string>
    <string>Ahmedabad</string>
  </city>
  <city>
    <string>GNR</string>
    <string>Gandhinagar</string>
  </city>
  <city>
    <string>PUN</string>
    <string>Pune</string>
  </city>
  <city>
    <string>RJT</string>
    <string>Rajkot</string>
  </city>
</India>

我正在尝试提取第二个 string 节点的值,其中第一个 string 节点值为 ADI

输出应仅为“艾哈迈达巴德”

尝试失败:

select t.my_xml.extract('/India/city/string[2]/text()').getStringVal() from XYZ t where t.my_xml.existsNode('/India/city[string[1] = "ADI"]') = 1;

上述查询的输出是AhmedabadGandhinagarPuneRajkot

预期输出:Ahmedabad

这里如何提取string节点的特定节点值?

【问题讨论】:

    标签: sql xml oracle extract oracle-xml-db


    【解决方案1】:

    您要选择具有 ADI 文本作为第一个字符串的节点。

    试试这个:

    select 
        t.my_xml.extract('//city[./string[1]/text() = "ADI"]/string[2]/text()').getStringVal()
    from XYZ t
        where t.my_xml.existsNode('/India/city[string[1] = "ADI"]') = 1;
    

    【讨论】:

      【解决方案2】:

      使用XMLTable 提取值:

      SELECT t.*
      FROM   XYZ x,
             XMLTable(
               '/India/city'
               PASSING x.my_xml
               COLUMNS string1 CHAR(3)      PATH './string[1]',
                       string2 VARCHAR2(20) PATH './string[2]'
             ) t
      WHERE  t.string1 = 'ADI';
      

      【讨论】:

      • 只是出于好奇,使用 XMLTable 优于 extract() 有什么优势?
      • @Kishan EXTRACT()EXTRACTVALUE() 在 Oracle 12c 中均已弃用(但包含在内是为了向后兼容) - Oracle 建议改用 XMLTable
      • @Kishan 除此之外,如果你想要多个值,那么你只需要调用一次XMLTable - 将其与EXTRACTVALUE 查询进行比较,在SELECT 子句中调用一次,然后您需要在WHERE 子句中再次调用它(或EXISTSNODE)。
      • @Kishan 使用VARCHAR2(4000) 或一些足够大的值代替。或者您可以返回到外部用户并获取正在使用的数据交换格式的规范。
      • @Kishan Oracle 对XMLTABLE 的规范使数据类型看起来是强制性的,但它似乎在没有数据类型的情况下也能工作——所以你可以省略它。
      【解决方案3】:

      1) 使用 xmlquery 和 flwor xquery

      select xmlcast( xmlquery('for $i in ./India/city where $i//string[1]/text() = $cond return $i/string[2]/text()' passing xmltype(q'~<India>
        <city>
          <string>ADI</string>
          <string>Ahmedabad</string>
        </city>
        <city>
          <string>GNR</string>
          <string>Gandhinagar</string>
        </city>
        <city>
          <string>PUN</string>
          <string>Pune</string>
        </city>
        <city>
          <string>RJT</string>
          <string>Rajkot</string>
        </city>
      </India>~'), 'ADI' as "cond"    returning content) as varchar2(20)) result  from dual; 
      

      2) 如果您期望不止一行,请尝试使用 xmltable。

      select *  from xmltable('$doc/India/city' passing xmltype(q'~<India>
        <city>
          <string>ADI</string>
          <string>Ahmedabad</string>
        </city>
        <city>
          <string>GNR</string>
          <string>Gandhinagar</string>
        </city>
        <city>
          <string>PUN</string>
          <string>Pune</string>
        </city>
         <city>
          <string>ADI</string>
          <string>Ahmedabad</string>
        </city>
        <city>
          <string>RJT</string>
          <string>Rajkot</string>
        </city>
      </India>~') as "doc" 
      columns 
         string1 varchar2(20) path'./string[1]/text()'
         , string2 varchar2(20) path'./string[2]/text()'
      
      )
      where string1='ADI'
      

      和带有 flwor xquery 的 xmltable

      select column_value  from xmltable('for $el in $doc/India/city where $el//string[1]/text() = "ADI" return $el/string[2]/text()' passing xmltype(q'~<India>
        <city>
          <string>ADI</string>
          <string>Ahmedabad</string>
        </city>
        <city>
          <string>GNR</string>
          <string>Gandhinagar</string>
        </city>
        <city>
          <string>PUN</string>
          <string>Pune</string>
        </city>
         <city>
          <string>ADI</string>
          <string>Ahmedabad</string>
        </city>
        <city>
          <string>RJT</string>
          <string>Rajkot</string>
        </city>
      </India>~') as "doc" )
      ;
      

      【讨论】:

        猜你喜欢
        • 2016-04-27
        • 2018-07-30
        • 2014-08-06
        • 2012-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多