【问题标题】:How can I insert multiple xml nodes with XMLQuery (XQuery) in Oracle SQL?如何在 Oracle SQL 中使用 XMLQuery (XQuery) 插入多个 xml 节点?
【发布时间】:2016-03-16 06:48:12
【问题描述】:

我创建了以下测试用例来演示我的问题:

create table test_table (idx number, a varchar2(20), b varchar2(20));
insert into test_table values (1, 'item1', 'value1');
insert into test_table values (2, 'item2', 'value2');

select appendChildXML(
                        xmltype('<inventory></inventory>'),
                        '/inventory', 
                        xmlagg(
                          xmlelement("id", xmlattributes(tt.idx as "val"),
                            xmlelement("listing",
                              xmlelement("item",tt.a),
                              xmlelement("value",tt.b)
                        )))) as xml
from test_table tt
;

这给出了所需的输出:

<inventory>  
  <id val="1">  
    <listing>
      <item>item1</item>  
      <value>value1</value>  
    </listing>  
  </id>  
  <id val="2">  
    <listing>  
      <item>item2</item>  
      <value>value2</value>  
    </listing>  
  </id>  
</inventory>

但是,如果我尝试使用 XMLQuery,我会收到错误消息。

select XMLQuery(
                  (
                    'copy $tmp := . modify insert node '
                    || xmlagg(
                          xmlelement("id", xmlattributes(tt.idx as "val"),
                            xmlelement("listing",
                              xmlelement("item",tt.a),
                              xmlelement("value",tt.b)
                       )))
                    || ' as last into $tmp/inventory return $tmp'
                  )
                  PASSING xmltype('<inventory></inventory>') RETURNING CONTENT
                ) as xml
from test_table tt
;

错误:

ORA-19112: error raised during evaluation: 
XVM-01003: [XPST0003] Syntax error at 'id'
1   copy $tmp := . modify insert node <id val="1"><listing><item>item1</item><v
-                                                                                                                ^

19112. 00000 -  "error raised during evaluation: %s"
*Cause:    The error function was called during evaluation of the XQuery expression.
*Action:   Check the detailed error message for the possible causes.

我认为问题与我插入多个 id 节点这一事实有关,因为如果表中只有一个节点,它将起作用,但我不明白为什么 appendChildXML 会起作用而 XMLQuery 不会。

我猜我可能需要使用 FLWOR 表达式,但我无法创建一个有效的表达式。

我目前正在使用 Oracle 11g 并将迁移到 12c(由于 appendChildXML 在 12c 中已弃用,因此尝试迁移到 XMLQuery)。我在 Oracle 中几乎没有使用 XML 的经验,也没有以前的 XMLQuery 经验。

谁能提供有关如何使 XMLQuery 工作的建议?谢谢!

【问题讨论】:

    标签: sql xml oracle11g appendchild xquery-sql


    【解决方案1】:

    您可以使用 ora:view 函数查询表,然后使用 FLWOR 表达式生成 XML,如下所示:

    10/12/2015 19:53:25:SQL> SELECT XMLQuery('<inventory>
      2                   {for $i in ora:view("TEST_TABLE")
      3                     let $idval := $i/ROW/IDX,
      4                         $item  := $i/ROW/A/text(),
      5                         $value := $i/ROW/B/text()
      6                     return <id val="{$idval}">
      7                               <listing>
      8                                 <item>{$item}</item>
      9                                 <value>{$value}</value>
     10                               </listing>
     11                             </id>}
     12                   </inventory>'
     13                  RETURNING CONTENT) AS test_xml
     14    FROM DUAL;
    
    TEST_XML
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    <inventory><id val="1"><listing><item>item1</item><value>value1</value></listing></id><id val="2"><listing><item>item2</item><value>value2</value></listing></id></inventory>
    

    【讨论】:

    • 现有库存节点将位于何处(文件、表、变量)?我们如何获得它以与新的 ID 子节点“合并”?
    • 现有库存节点在实际实现中将位于一个表中,这将在更新语句中使用。通过给它一个空白的库存节点,我能够在测试选择语句中模仿它。再次感谢!
    【解决方案2】:

    我能够通过以下查询获得所需的结果。感谢 Francisco Sitja 的回答和 FLWOR 表达,引导我找到完整的答案。

    select XMLQuery(
                      (
                        'copy $tmp := . modify insert node '
                        || 'for $i in ora:view("TEST_TABLE")
                              let $idval := $i/ROW/IDX,
                                  $item  := $i/ROW/A/text(),
                                  $value := $i/ROW/B/text()
                             return <id val="{$idval}">
                                      <listing>
                                        <item>{$item}</item>
                                        <value>{$value}</value>
                                      </listing>
                                    </id>'
                        || ' as last into $tmp/inventory return $tmp'
                      )
                      PASSING xmltype('<inventory></inventory>') RETURNING CONTENT
                    ) as xml
    from dual;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-11
      • 2021-10-30
      • 2018-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-24
      • 2020-11-13
      相关资源
      最近更新 更多