sql - 使用 PL/SQL 解析 XML 时跳过重复值

标签 sql xml plsql oracle11g

我有以下 XML 结构,该结构是从 Web 服务中提取并存储在 PL/SQL 中的 XMLTYPE 变量中:

     <results>
        <return>
            <customerid>127</customerid>
            <customername>Test1</customername>
        </return>
        <return>
            <customerid>127</customerid>
            <customername>Test1</customername></return>
        <return>
            <customerid>93</customerid>
            <customername>Test2</customername>
        </return>
        <return>
            <customerid>96</customerid>
            <customername>Test3</customername>
        </return>
     </results>

由于我正在使用的 Web 服务不灵活,无法指定仅出现 1 次的 customerid 及其相应值。考虑到这一点,我如何使用 PL/SQL 解析此 XML 文档以仅检索每个客户 ID 的第一次出现?

例如,解析上面的内容将返回:

       127 Test1
       93 Test2
       96 Test3

我的想法是开始解析 XML 并针对空数组查询客户 ID 是否存在(已打印到屏幕上)。如果没有,则打印客户 ID 和屏幕上匹配的名称,并将客户 ID 添加到数组中。这意味着下次该 XML 标记将被跳过并移至下一个标记,至少这是我可以在 PHP 中执行的操作,但遗憾的是这一次我必须使用 PL/SQL。

关于在 PL/SQL 中执行此操作的最有效方法有什么想法吗?

干杯,

杰森

附加:如有必要,我可以更改 XML 文档的结构,因为我自己使用 PL/SQL 即时生成它。

最佳答案

将所有节点提取到数据集并选择不同的值:

SQLFiddle

with params as (
  select 
    xmltype('  
     <results>
        <return>
            <customerid>127</customerid>
            <customername>Test1</customername>
        </return>
        <return>
            <customerid>127</customerid>
            <customername>Test1</customername></return>
        <return>
            <customerid>93</customerid>
            <customername>Test2</customername>
        </return>
        <return>
            <customerid>96</customerid>
            <customername>Test3</customername>
        </return>
     </results>
   ') p_xml 
 from dual
) 
select 
  distinct customer_id, customer_name 
from 
  XMLTable(
    '
      for $i in $doc/results/return     
        return $i
    '
    passing (select p_xml from params) as "doc"
    columns
      customer_id   number         path '//customerid',
      customer_name varchar2(4000) path '//customername'
  )

另一种解析方式:

SQLFiddle

with params as (
  select 
    sys.xmltype('  
     <results>
        <return>
            <customerid>127</customerid>
            <customername>Test1</customername>
        </return>
        <return>
            <customerid>127</customerid>
            <customername>Test1</customername></return>
        <return>
            <customerid>93</customerid>
            <customername>Test2</customername>
        </return>
        <return>
            <customerid>96</customerid>
            <customername>Test3</customername>
        </return>
     </results>
   ') p_x 
 from dual
) 
select distinct
 extractvalue(column_value, '//customerid') customer_id,
 extractvalue(column_value, '//customername') customer_name
from 
  table(XMLSequence((select extract(p_x, '/results/return') x from params)))

如果需要,从数据集重建 XML:

SQLFiddle

with params as (
  select 
    sys.xmltype('  
      -- same XML text as in previous examples ------- 
   ') p_x 
 from dual
) 
select 
  XMLElement("results",
    XMLAgg(
      XMLElement("return",
        XMLConcat(
          XMLElement("customerid", customer_id),
          XMLElement("customername", customer_name)
        )
      )
    )           
  ).getclobval()  
from (  
  select distinct
   extractvalue(column_value, '//customerid') customer_id,
   extractvalue(column_value, '//customername') customer_name
  from 
    table(XMLSequence((select extract(p_x, '/results/return') x from params)))
)

关于sql - 使用 PL/SQL 解析 XML 时跳过重复值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18147050/

相关文章:

oracle - 修复 Oracle 4000 字符中允许的最大长度

android - 在ConstraintLayout中链接两个障碍

database - 如何在Oracle数据库中写两个字母之间的select?

多个表每周的 SQL 计数摘要

mysql - 有关如何使用 CASE 按与大多数单词的最佳匹配进行排序的 SQL 语法

php - 使用 php 和 'if changed' 选项创建 xml

C# 反序列化递归类

sql - 为什么 SQL Server 中的输出不同而 Oracle 中的输出相同?

SQL删除除某些行之外的所有行

sql server 2005 .mdf .ldf 文件