我试图对表格进行数据处理。该表包含使用CLOB数据类型存储xml消息的列。 XML消息具有以下结构:
<t:MsgNameXML typeInfo="source" xsi:schemaLocation="http://example/location FileName.xsd" xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace" >
<t:info1>data1</t:info1>
<t:info2>data2</t:info2>
<t:Section>
<t:SubSection>
<t:SubSubSection>
<t:variable1>data3</t:variable1>
<t:variable2>data4</t:variable2>
</t:SubSubSection>
</t:SubSection>
</t:Section>
<t:Section>
<t:SubSection>
<t:SubSubSection>
<t:variable1>data5</t:variable1>
<t:variable2>data6</t:variable2>
</t:SubSubSection>
</t:SubSection>
</t:Section>
</t:MsgNameXML>
所以,至少对我来说,主要的困难是命名空间和存在多个节点的事实。
我希望得到以下输出(对于包含上述XML的记录):
INFO1 INFO2 VARIABLE1 VARIABLE2
-------------------------------------
data1 data2 data3 data4
data1 data2 data5 data6
我构建了以下查询以尝试提取&#34; variable1&#34; (Oracle数据库,所以PL SQL,我猜):
select
extractvalue(xmltype(CLOB_COLUMN_NAME),
'/t:MsgNameXML/t:Section/t:SubSection/t:SubSubSection/t:variable1',
'xmlns:t="xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace"')
from
TABLE_NAME,
TABLE(XMLSEQUENCE(EXTRACT(CLOB_COLUMN_NAME, '/t:MsgNameXML/t:Section/t:SubSection/t:SubSubSection/t:variable1')))
遗憾的是,这会产生以下错误消息:
ORA-00932: inconsistent datatypes: expected - got -
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*Cause:
*Action:
Error at Line: 9 Column: 33
(第9行,第33列,指的是CLOB_COLUMN_NAME位于from子句中的EXTRACT函数之后的位置。)
有谁知道我做错了什么,我怎么能纠正这个?
此外,我需要扩展此查询以从XML消息中提取更多值,而不仅仅是&#34; variable1&#34; (见上面所需的结果)。对此的任何帮助也将非常感激。
感谢您的帮助,
汤姆
答案 0 :(得分:1)
您的ORA-00932的直接原因是您试图直接从CLOB中提取;你已经在一个地方转换了,但是这个:
TABLE(XMLSEQUENCE(EXTRACT(CLOB_COLUMN_NAME, ... )))
......需要:
TABLE(XMLSEQUENCE(EXTRACT(XMLType(CLOB_COLUMN_NAME), ... )))
但是该命名空间仍然没有得到认可,如果您只改变它,那么您将获得ORA-31011。您可以通过在EXTRACT
调用中包含命名空间来解决问题,并纠正错误:
select extractvalue(column_value, '/t:variable1',
'xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace"')
as variable1
from
TABLE_NAME,
TABLE(XMLSEQUENCE(EXTRACT(XMLType(CLOB_COLUMN_NAME),
'/t:MsgNameXML/t:Section/t:SubSection/t:SubSubSection/t:variable1',
'xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace"')));
VARIABLE1
----------
data3
data5
或者通过将提取物移回一个级别来同时显示两个变量:
select extractvalue(column_value, 't:SubSubSection/t:variable1',
'xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace"')
as variable1,
extractvalue(column_value, 't:SubSubSection/t:variable2',
'xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace"')
as variable2
from
TABLE_NAME,
TABLE(XMLSEQUENCE(EXTRACT(XMLType(CLOB_COLUMN_NAME),
'/t:MsgNameXML/t:Section/t:SubSection/t:SubSubSection',
'xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace"')));
VARIABLE1 VARIABLE2
---------- ----------
data3 data4
data5 data6
包括信息值也会使其变得更加复杂和重复:
select extractvalue(XMLType(CLOB_COLUMN_NAME), 't:MsgNameXML/t:info1',
'xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace"')
as info1,
extractvalue(XMLType(CLOB_COLUMN_NAME), 't:MsgNameXML/t:info2',
'xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace"')
as info2,
extractvalue(column_value, 't:SubSubSection/t:variable1',
'xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace"')
as variable1,
extractvalue(column_value, 't:SubSubSection/t:variable2',
'xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace"')
as variable2
from
TABLE_NAME,
TABLE(XMLSEQUENCE(EXTRACT(XMLType(CLOB_COLUMN_NAME),
'/t:MsgNameXML/t:Section/t:SubSection/t:SubSubSection',
'xmlns:t="http://url/of/custom/namespace" xmlns:"http://url/of/default/namespace"')));
INFO1 INFO2 VARIABLE1 VARIABLE2
---------- ---------- ---------- ----------
data1 data2 data3 data4
data1 data2 data5 data6
SQL Fiddle这种方法。
您可以使用XQuery and XMLTable代替旧的提取语法:
select info1, info2, variable1, variable2
from table_name,
xmltable('declare namespace t = "http://url/of/custom/namespace"; (: :)
for $i in /t:MsgNameXML
let $info1 := $i/t:info1,
$info2 := $i/t:info2
for $j in $i/t:Section/t:SubSection/t:SubSubSection
let $variable1 := $j/t:variable1,
$variable2 := $j/t:variable2
return <tmp>
<info1>{$info1}</info1>
<info2>{$info2}</info2>
<variable1>{$variable1}</variable1>
<variable2>{$variable2}</variable2>
</tmp>'
passing xmltype(CLOB_COLUMN_NAME)
columns
info1 char(10) path '/tmp/info1',
info2 char(10) path '/tmp/info2',
variable1 char(10) path '/tmp/variable1',
variable2 char(10) path '/tmp/variable2'
);
INFO1 INFO2 VARIABLE1 VARIABLE2
---------- ---------- ---------- ----------
data1 data2 data3 data4
data1 data2 data5 data6
我必须稍微调整CLOB值以使其有效;将xsi=
更改为xmlns:xsi=
并为默认命名空间xmlns:x="http://url/of/default/namespace"
设置虚拟名称。我想那都是......
XQuery是一种基于序列&#34;的功能语言,它使用"FLOWR" expressions。特别是两个for
循环遍历结构,let
表达式将命名空间变量分配给局部变量,然后以更简单的XML结构返回,从中可以通过新路径提取列。 (您似乎无法直接在path
字符串中使用名称空间。)
扩展此功能可以非常轻松地从您的消息中获取更多价值 - 更多let
个表达式和更多匹配的path
提取。
但我自己真的只是抓住这些东西的表面,所以可能有更简单/更好/更快的方法来做到这一点;无论如何,希望是XQuery方法的起点。