使用 XMLtable 列是否可以将集合数据类型分配给 xmltable 列

问题描述

我有一个要求,我必须将 XML 表列选择为记录数据类型,该数据类型是静态数据类型和集合的组合。我搜索了各种来源,说 Xpath 可以返回节点列表,但我怀疑是否可以使用列的集合数据类型来存储此节点列表。

  type MobileTable is Table of number Index by pls_integer; 

    type purchase is record (vegetables varchar2(20),fruits varchar2(30));
 
    type food is table of purchase Index by pls_integer;
     type data is record
    (Name varchar2(30),Mobile_Number MobileTable,Purchases food);
 


    <customers>
    <month>July</month>
    <day>Tuesday</day>
    <start-time>11</start-time>
     <customer>
    <Name>sally</Name>
    <Mobile-Number>999-256-00</Mobile-Number>
    <Mobile-Number>999-256-11</Mobile-Number>
    <purchase>
    <vegetables>Carrot</vegetables>
    <fruits>Apple</fruits>
    </purchase>
    <purchase>
    <vegetables>broccli</vegetables>
    <fruits>Orange</fruits>
    </purchase>
    <customer>
    </customers>

about XML 只是我用来解释我的需求的一个例子,如果问题不清楚,请提出建议。

我的查询

    select Name,Mobile_Number,Purchases into  data from custommers_table ct,xmltable('customers' 
        passing ct.cust_xml
        columns Name varchar2(20) path 'Name',Mobile_Number MobileTable path 'Mobile-Number',Purchases food path '//purchase/vegetables|//purchase/fruit')
where cust_xml_id=1;

在 Mobile_Number 和 Purchases 的情况下,我收到无效的数据类型错误

//purchase/vegetables|//purchase/fruit

我在 W3 学校的 Xpath 语法概念下发现了这个 XPath,我不确定它的正确性,但这就是我想要实现的目标。

请建议我是否还有其他方法可以实现这一点。

解决方法

作为一种相当暴力的方法,您可以将手机号码和购买作为子 xmltype 变量获取,并在循环中填充集合:

declare
  type t_mobile_numbers_tab is table of varchar2(15) index by pls_integer; 

  type t_purchase_rec is record (
    vegetables varchar2(20),fruits varchar2(30)
  );
  type t_purchases_tab is table of t_purchase_rec index by pls_integer;

  type t_data_rec is record (
    name varchar2(30),mobile_numbers t_mobile_numbers_tab,purchases t_purchases_tab
  );

  l_data t_data_rec;
  l_mobile_numbers xmltype;
  l_purchases xmltype;
begin
  select name,mobile_numbers,purchases
  into l_data.name,l_mobile_numbers,l_purchases
  from custommers_table ct
  cross apply xmltable('customers/customer' 
    passing ct.cust_xml
    columns name varchar2(20) path 'Name',mobile_numbers xmltype path 'Mobile-Number',purchases xmltype path 'purchase/vegetables|purchase/fruits'
  )
  where cust_xml_id=1;

  for r in (
    select mobile_number
    from xmltable('Mobile-Number'
      passing l_mobile_numbers
      columns mobile_number varchar2(15) path '.'
    )
  )
  loop
    l_data.mobile_numbers(l_data.mobile_numbers.count) := r.mobile_number;
  end loop;

  for r in (
    select type,purchase
    from xmltable('*'
      passing l_purchases
      columns type varchar2(10) path 'name(.)',purchase varchar2(30) path '.'
    )
  )
  loop
    if r.type = 'vegetables' then
      l_data.purchases(l_data.purchases.count).vegetables := r.purchase;
    elsif r.type = 'fruits' then
      l_data.purchases(l_data.purchases.count).fruits := r.purchase;
    end if;
  end loop;
end;
/

第一个查询获取标量名称和两个子 xmltype 值。然后在游标查询中使用这些 xmltype 变量,在这些游标循环中,数字/购买被提取并分配给子集合中的记录。

db<>fiddle 显示中间值,并打印出集合的内容以查看填充的内容。

对于对象类型而不是记录,这会更简单一些;但仍然觉得可能有更有效的方法。