我使用的是Oracle版本 - 11.2.0.4
我已经在下面以更简化的方式重现了我面临的问题。 我有2个带有XMLTYPE列的表。 表1(以下示例中的base_table)将XMLTYPE的存储模型作为BINARY XML。 表2(my_tab)将XMLTYPE的存储模型作为CLOB。
使用base_table中的XML,我可以根据特定条件提取属性的值。该属性又是my_tab中包含的xml中的节点名称,我想从my_tab中提取该节点的值。 请注意,我现在无权改变这种逻辑。
代码工作正常,直到XMLTYPE列的存储模型在两个表中都是CLOB。最近重新创建了base_table(drop和create),因此它的存储模型被修改为BINARY XML,据我所知,它是版本11.2.0.4中的默认存储模型
这是create table stmt和sample data -
create table base_table(xml xmltype);
create table my_tab(xml xmltype)
xmltype column "XML" store as clob;
insert into base_table(xml)
values (xmltype('<ROOT>
<ELEMENT NAME="NODEA">
<NODE1>A-Node1</NODE1>
<NODE2>A-Node2</NODE2>
</ELEMENT>
<ELEMENT NAME="NODEB">
<NODE1>B-Node1</NODE1>
<NODE2>B-Node2</NODE2>
</ELEMENT>
<ELEMENT NAME="NODEC">
<NODE1>C-Node1</NODE1>
<NODE2>C-Node2</NODE2>
</ELEMENT>
</ROOT>')
);
insert into my_tab(xml)
values (xmltype('<TEST_XML>
<SOME_NODE>
<XYZ>
<NODEB>My area of concern</NODEB>
<OTHER_NODE> Something irrelevant </OTHER_NODE>
</XYZ>
</SOME_NODE>
<SOME_OTHER_NODE>
<ABC> Some value for this node </ABC>
</SOME_OTHER_NODE>
</TEST_XML>')
);
以下查询失败:
select extract(t.xml, sd.tag_name).getstringval()
from (select '//' || extract(value(d), '//@NAME').getstringval() || '/text()' as tag_name
from base_table b,
table(xmlsequence(extract(b.xml, '//ROOT/ELEMENT'))) d
where extract(value(d), '//NODE2/text()').getstringval() = 'B-Node2') sd,
my_tab t;
ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00601: Invalid token in: '///text()'
但是,此查询工作正常,并且能够提取感兴趣的节点I的值。可以看出,tag_name是根据需要获取的,但是当它在&#34; extract&#34中使用时;它的价值以某种方式丢失。
select sd.tag_name, extract(t.xml, '//NodeB/text()').getstringval()
from (select '//' || extract(value(d), '//@NAME').getstringval() || '/text()' as tag_name
from base_table b,
table(xmlsequence(extract(b.xml, '//ROOT/ELEMENT'))) d
where extract(value(d), '//NODE2/text()').getstringval() = 'B-Node2') sd,
my_tab t;
如果我将base_table的XMLTYPE存储模型更改回CLOB,则错误的查询会再次正常工作。
我想了解存储模型作为BINARY XML出了什么问题。
我修改了如下查询,工作正常。即转换为clob并返回XMLTYPE:
select extract(t.xml, sd.tag_name).getstringval()
from (select '//' || extract(value(d), '//@NAME').getstringval() || '/text()' as tag_name
from base_table b,
table(xmlsequence(extract(XMLTYPE(b.xml.getclobval()), '//ROOT/ELEMENT'))) d
where extract(value(d), '//NODE2/text()').getstringval() = 'B-Node2') sd,
my_tab t;
谢谢, 凯拉什