如何在 Oracle SQL 中使用 XMLQuery (XQuery) 插入多个 xml 节点?
How can I insert multiple xml nodes with XMLQuery (XQuery) in Oracle SQL?
我创建了以下测试用例来演示我的问题:
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 节点这一事实有关,因为如果我在 table 中只有一个 id 节点,它就可以工作,但我不明白为什么 appendChildXML 将起作用,而 XMLQuery 将不起作用。
我猜我可能需要使用 FLWOR 表达式,但我无法创建一个有效的表达式。
我目前正在使用 Oracle 11g,并将迁移到 12c(尝试迁移到 XMLQuery,因为 appendChildXML 在 12c 中已弃用)。我在 Oracle 中使用 XML 的经验很少,并且以前没有 XML 查询经验。
任何人都可以提供有关如何使 XML 查询正常工作的建议吗?谢谢!
你可以使用ora:view函数查询table,然后用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>
我能够通过下面的查询获得我需要的结果。感谢 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;
我创建了以下测试用例来演示我的问题:
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 节点这一事实有关,因为如果我在 table 中只有一个 id 节点,它就可以工作,但我不明白为什么 appendChildXML 将起作用,而 XMLQuery 将不起作用。
我猜我可能需要使用 FLWOR 表达式,但我无法创建一个有效的表达式。
我目前正在使用 Oracle 11g,并将迁移到 12c(尝试迁移到 XMLQuery,因为 appendChildXML 在 12c 中已弃用)。我在 Oracle 中使用 XML 的经验很少,并且以前没有 XML 查询经验。
任何人都可以提供有关如何使 XML 查询正常工作的建议吗?谢谢!
你可以使用ora:view函数查询table,然后用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>
我能够通过下面的查询获得我需要的结果。感谢 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;