【问题标题】:Oracle XMLTABLE Function. How to merge nodes that have the same name?Oracle XMLTABLE 函数。如何合并具有相同名称的节点?
【发布时间】:2021-12-30 16:05:02
【问题描述】:

对帖子进行了编辑以提供一个可重复的最小示例

我正在寻找一种方法来连接所有名称节点(可能是 2-3-4 等)以及它们之间的空间。以下示例给出错误ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence。我知道这是因为有多个名称节点。

我尝试替换

"name" VARCHAR2(50) PATH 'name'

"name" VARCHAR2(50) PATH 'name[1]' 只会给出第一个值。这会消除错误,但不会将它们连接在一起。

WITH XML_T (XML_FILE_DATA) AS (SELECT '<breakfast_menu>
    <food>
        <name>Belgian Waffles</name>
        <name>Cake</name>
        <price>$5.95</price>
        <calories>650</calories>
    </food>
    <food>
        <name>Belgian Waffles(2)</name>
        <name>Cake(2)</name>
        <price>$5.95(2)</price>
        <calories>650(2)</calories>
    </food>
</breakfast_menu>' FROM DUAL)
SELECT x.*
  FROM XML_T,
       XMLTABLE ('/breakfast_menu/food'
                 PASSING xmltype (XML_T.XML_FILE_DATA)
                 COLUMNS    "name"        VARCHAR2(50) PATH 'name',
                            "price"       VARCHAR2(50) PATH 'price',
                            "calories"    VARCHAR2(50) PATH 'calories') X;   

我希望能够获取 2 个名称并将它们合并到一个列中。期望的输出:

+-------------------------+-------------+-------------+
| name                    |       price |    calories |
+-------------------------+-------------+-------------+
| Belgian Waffles Cake    |       $5.95 |         650 |
| Belgian Waffles Cake(2) |    $5.95(2) |      650(2) |
+-------------------------+-------------+-------------+

@Padders Answer 解决了这个问题。

【问题讨论】:

  • 在提出问题时,您需要提供一个最小可重现示例: (1) 输入 XML。 (2) 你的逻辑,以及试图实现它的 SQL。 (3) 基于上述#1 的期望输出。
  • 我尽力写了,我有我使用的xml、逻辑和sql。我能想到的唯一做得更好的事情就是举一个例子,就像我收到的答案中包含 PL/SQL 中的 xml 但我不知道如何包含它,因为我有它在一个表中。以及我写的想要的输出,我想将节点合并到 Belgian Waffles Cake 中。
  • @Yitzhak Khabinsky 我稍后会尝试对帖子进行编辑,以使其更易于理解,并尝试使其更接近最小的可重现示例。我猜最好的办法是有一段代码,你可以复制粘贴它来测试它。但是我应该对我的初始帖子进行额外的编辑,还是修改我写的内容并改变它的方式?
  • 请阅读this,了解一些改进问题的技巧。

标签: xml oracle xml-parsing oracle-sqldeveloper xmltable


【解决方案1】:

您可以在 PATH 字符串中使用 Oracle 对 xquery 表达式的支持,例如

SELECT xt.*
FROM   xml_t x,
       XMLTABLE (
           'breakfast_menu/food'
           PASSING x.xml_file_data
           COLUMNS
              names VARCHAR2 (4000) PATH 'string-join(name," ")',
              price VARCHAR2 (50) PATH 'price',
              calories VARCHAR2 (50) PATH 'calories') xt;  

【讨论】:

  • 我认为这可能是最好的方法。它很棒,易于理解,无论我有多少节点,它似乎都在工作。我不是专家,但这似乎比第一个答案更好
  • 好答案,我这边+1!
【解决方案2】:

您可以像这样在 XPath 选择器中指定要查找的 名称

WITH xml_t (xml_file_data) AS (SELECT '<breakfast_menu>
    <food>
        <name>Belgian Waffles</name>
        <name>Cake</name>
        <price>$5.95</price>
        <calories>650</calories>
    </food>
    <food>
        <name>Belgian Waffles(2)</name>
        <name>Cake(2)</name>
        <price>$5.95(2)</price>
        <calories>650(2)</calories>
    </food>
</breakfast_menu>' FROM DUAL)
SELECT TRIM (name1 || ' ' || name2 || ' ' || name3 || ' ' || name4) AS combined_names, x.*
  FROM xml_t,
       XMLTABLE ('/breakfast_menu/food'
                 PASSING xmltype (XML_T.XML_FILE_DATA)
                 COLUMNS name1 VARCHAR2 (50) PATH 'name[1]',
                         name2 VARCHAR2 (50) PATH 'name[2]',
                         name3 VARCHAR2 (50) PATH 'name[3]',
                         name4 VARCHAR2 (50) PATH 'name[4]',
                         price VARCHAR2 (50) PATH 'price',
                         calories VARCHAR2 (50) PATH 'calories') X;



               COMBINED_NAMES                 NAME1      NAME2    NAME3    NAME4       PRICE    CALORIES
_____________________________ _____________________ __________ ________ ________ ___________ ___________
Belgian Waffles Cake          Belgian Waffles       Cake                         $5.95       650
Belgian Waffles(2) Cake(2)    Belgian Waffles(2)    Cake(2)                      $5.95(2)    650(2)

【讨论】:

  • 我想将名称列合并,而不是将它们作为单独的列。 "name1" VARCHAR2 (50) PATH 'name[1]', "name2" VARCHAR2 (50) PATH 'name[2]', 如果我删除这两列,它还能工作吗?它似乎给了我错误
  • 基本上结果看起来不错,只是没有 name1 和 name 2 列。所以它只有 3 列:COMBINED_NAMES、PRICE 和 CALORIES
  • 您所要做的就是修改您选择的列,例如SELECT TRIM (name1 || ' ' || name2 || ' ' || name3 || ' ' || name4) AS combined_names, x.price, x.calories FROM....
  • 修改AS combined_names, x.price, x.calories FROM后,就有了想要的输出。因此,您放置所有列,然后选择您需要的列。一个问题:如果我有更多的名字,我会继续添加nameX VARCHAR2 (50) PATH 'name[X]', 等等?除此之外非常感谢它有帮助! :)
  • 是的,您可以继续在 XMLTABLE 表达式的列列表中添加额外的 nameX 列,然后将它们连接到您的 COMBINED_NAMES 列中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-31
相关资源
最近更新 更多