如何从xmltable中的不同级别获取数据?
how to get data from different levels in a xmltable?
我正在尝试从 VENDOR_XML 列的 table MVR_DTL 中获取两个属性的值。 VENDOR_XML 是 clob 数据类型,包含一个 xml 看起来像这样
<MVRCHPINFF_1.0>
<Routing ReplyToQMgr="PQ21" ReplyToQ="A4218QA.BIZTALK.REPLY.REPORT.PROD" CorelId="712393102361590" MsgType="8" Expiry="-1" MsgID="201904051632015"></Routing>
<MVRRecLoop>
<CLoop>
<CRec>
<C_MVRNumberAddr>ROMAN GENERAL</C_MVRNumberAddr>
</CRec>
<CRec>
<C_MVRNumberAddr>ROMAN ST</C_MVRNumberAddr>
</CRec>
<CRec>
<C_MVRNumberAddr>ROMAN CITY, ROME 111111</C_MVRNumberAddr>
</CRec>
</CLoop>
<HIJLoop>
<JRec>
<J_SVCDesc>MVR RECORD CLEAR</J_SVCDesc>
</JRec>
</HIJLoop>
</MVRRecLoop>
</MVRCHPINFF_1.0>
我试过了运行
SELECT c.J_SVCDesc, c.XMLDetails from MVR_DTL M,
XMLTABLE(
'string-join(/MVRCHPINFF_1.0/MVRRecLoop/CLoop/CRec/C_MVRNumberAddr, "|")'
passing XMLTYPE(M.VENDOR_XML)
columns XMLDetails varchar2(200) PATH '.',
J_SVCDesc varchar2(50) PATH './../../../HIJLoop/JRec/J_SVCDesc') c;
我收到这个错误
Error during Execute
S1000(19112)[Oracle][ODBC][Ora]ORA-19112: error raised during evaluation:
XVM-01020: [XPTY0020] The path step context item is not a node
我也试过了
SELECT x1.J_SVCDesc, x2.XMLDetails from MVR_DTL M,
XMLTABLE('/MVRCHPINFF_1.0/MVRRecLoop'
passing XMLTYPE(M.VENDOR_XML)
columns
Address XMLTYPE path './CLoop/CRec/C_MVRNumberAddr',
J_SVCDesc varchar(50) PATH './HIJLoop/JRec/J_SVCDesc') x1
CROSS JOIN XMLTable(
'string-join(., "|")'
PASSING x1.Address
COLUMNS XMLDetails varchar2(200) PATH '.') x2;
但出错了
Error during Execute
S1000(19279)[Oracle][ODBC][Ora]ORA-19279: XPTY0004 - XQuery dynamic type mismatch:
expected singleton sequence - got multi-item sequence
我正在尝试获取
J_SVCDESC XMLDETAILS
MVR RECORD CLEAR ROMAN GENERAL|ROMAN ST|ROMAN CITY, ROME 111111
谁能帮我弄清楚我错过了什么。
您可以将字符串连接向下移动到列子句:
select x.j_svcdesc, x.xmldetails
from mvr_dtl m
cross join xmltable (
'/MVRCHPINFF_1.0/MVRRecLoop'
passing xmltype(m.vendor_xml)
columns J_SVCDesc varchar2(50) path 'HIJLoop/JRec/J_SVCDesc',
xmldetails varchar2(200) path 'string-join(CLoop/CRec/C_MVRNumberAddr, "|")'
) x
在 CTE 中使用示例数据进行演示:
with mvr_dtl (vendor_xml) as (
select to_clob('<MVRCHPINFF_1.0>
<Routing ReplyToQMgr="PQ21" ReplyToQ="A4218QA.BIZTALK.REPLY.REPORT.PROD" CorelId="712393102361590" MsgType="8" Expiry="-1" MsgID="201904051632015"></Routing>
<MVRRecLoop>
<CLoop>
<CRec>
<C_MVRNumberAddr>ROMAN GENERAL</C_MVRNumberAddr>
</CRec>
<CRec>
<C_MVRNumberAddr>ROMAN ST</C_MVRNumberAddr>
</CRec>
<CRec>
<C_MVRNumberAddr>ROMAN CITY, ROME 111111</C_MVRNumberAddr>
</CRec>
</CLoop>
<HIJLoop>
<JRec>
<J_SVCDesc>MVR RECORD CLEAR</J_SVCDesc>
</JRec>
</HIJLoop>
</MVRRecLoop>
</MVRCHPINFF_1.0>')
from dual
)
select x.j_svcdesc, x.xmldetails
from mvr_dtl m
cross join xmltable (
'/MVRCHPINFF_1.0/MVRRecLoop'
passing xmltype(m.vendor_xml)
columns J_SVCDesc varchar2(50) path 'HIJLoop/JRec/J_SVCDesc',
xmldetails varchar2(200) path 'string-join(CLoop/CRec/C_MVRNumberAddr, "|")'
) x;
J_SVCDESC XMLDETAILS
-------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MVR RECORD CLEAR ROMAN GENERAL|ROMAN ST|ROMAN CITY, ROME 111111
如果 HIJLoop 节点名称表明也可能有多个 JRec 值,那么您也可以将它们连接起来:
columns J_SVCDesc varchar2(50) path 'string-join(HIJLoop/JRec/J_SVCDesc, "|")',
xmldetails varchar2(200) path 'string-join(CLoop/CRec/C_MVRNumberAddr, "|")'
这对示例 XML.
的输出没有影响
顺便说一句,你的第二次尝试成功了;它没有错误,但也没有得到正确的结果。你传递的 address
是一个只有兄弟节点的 XML 片段,而字符串连接只看到一个值,由那些 text()
组成(我认为......类似的东西).如果您改为向下传递 CLoop 并展开第二个 XPath,那么它会起作用:
select x1.j_svcdesc, x2.xmldetails
from mvr_dtl m
cross join xmltable (
'/MVRCHPINFF_1.0/MVRRecLoop'
passing xmltype(m.vendor_xml)
columns J_SVCDesc varchar(50) path 'HIJLoop/JRec/J_SVCDesc',
HIJLoop xmltype path 'CLoop'
) x1
cross join xmltable (
'string-join(CLoop/CRec/C_MVRNumberAddr, "|")'
passing x1.HIJLoop
columns xmldetails varchar2(200) path '.'
) x2;
但是如果你真的得到 "ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence" 那么我怀疑你的数据实际上有多个 JRec 节点;在这种情况下,请参阅上面的第二个查询。
db<>fiddle 显示了这种方法和我的第一个查询的问题;它与我的第二个查询一起使用。所以你可能需要使用它:
select x.j_svcdesc, x.xmldetails
from mvr_dtl m
cross join xmltable (
'/MVRCHPINFF_1.0/MVRRecLoop'
passing xmltype(m.vendor_xml)
columns J_SVCDesc varchar2(50) path 'string-join(HIJLoop/JRec/J_SVCDesc, "|")',
xmldetails varchar2(200) path 'string-join(CLoop/CRec/C_MVRNumberAddr, "|")'
) x;
您可能还需要增加返回的列大小。
我正在尝试从 VENDOR_XML 列的 table MVR_DTL 中获取两个属性的值。 VENDOR_XML 是 clob 数据类型,包含一个 xml 看起来像这样
<MVRCHPINFF_1.0>
<Routing ReplyToQMgr="PQ21" ReplyToQ="A4218QA.BIZTALK.REPLY.REPORT.PROD" CorelId="712393102361590" MsgType="8" Expiry="-1" MsgID="201904051632015"></Routing>
<MVRRecLoop>
<CLoop>
<CRec>
<C_MVRNumberAddr>ROMAN GENERAL</C_MVRNumberAddr>
</CRec>
<CRec>
<C_MVRNumberAddr>ROMAN ST</C_MVRNumberAddr>
</CRec>
<CRec>
<C_MVRNumberAddr>ROMAN CITY, ROME 111111</C_MVRNumberAddr>
</CRec>
</CLoop>
<HIJLoop>
<JRec>
<J_SVCDesc>MVR RECORD CLEAR</J_SVCDesc>
</JRec>
</HIJLoop>
</MVRRecLoop>
</MVRCHPINFF_1.0>
我试过了运行
SELECT c.J_SVCDesc, c.XMLDetails from MVR_DTL M,
XMLTABLE(
'string-join(/MVRCHPINFF_1.0/MVRRecLoop/CLoop/CRec/C_MVRNumberAddr, "|")'
passing XMLTYPE(M.VENDOR_XML)
columns XMLDetails varchar2(200) PATH '.',
J_SVCDesc varchar2(50) PATH './../../../HIJLoop/JRec/J_SVCDesc') c;
我收到这个错误
Error during Execute
S1000(19112)[Oracle][ODBC][Ora]ORA-19112: error raised during evaluation:
XVM-01020: [XPTY0020] The path step context item is not a node
我也试过了
SELECT x1.J_SVCDesc, x2.XMLDetails from MVR_DTL M,
XMLTABLE('/MVRCHPINFF_1.0/MVRRecLoop'
passing XMLTYPE(M.VENDOR_XML)
columns
Address XMLTYPE path './CLoop/CRec/C_MVRNumberAddr',
J_SVCDesc varchar(50) PATH './HIJLoop/JRec/J_SVCDesc') x1
CROSS JOIN XMLTable(
'string-join(., "|")'
PASSING x1.Address
COLUMNS XMLDetails varchar2(200) PATH '.') x2;
但出错了
Error during Execute
S1000(19279)[Oracle][ODBC][Ora]ORA-19279: XPTY0004 - XQuery dynamic type mismatch:
expected singleton sequence - got multi-item sequence
我正在尝试获取
J_SVCDESC XMLDETAILS
MVR RECORD CLEAR ROMAN GENERAL|ROMAN ST|ROMAN CITY, ROME 111111
谁能帮我弄清楚我错过了什么。
您可以将字符串连接向下移动到列子句:
select x.j_svcdesc, x.xmldetails
from mvr_dtl m
cross join xmltable (
'/MVRCHPINFF_1.0/MVRRecLoop'
passing xmltype(m.vendor_xml)
columns J_SVCDesc varchar2(50) path 'HIJLoop/JRec/J_SVCDesc',
xmldetails varchar2(200) path 'string-join(CLoop/CRec/C_MVRNumberAddr, "|")'
) x
在 CTE 中使用示例数据进行演示:
with mvr_dtl (vendor_xml) as (
select to_clob('<MVRCHPINFF_1.0>
<Routing ReplyToQMgr="PQ21" ReplyToQ="A4218QA.BIZTALK.REPLY.REPORT.PROD" CorelId="712393102361590" MsgType="8" Expiry="-1" MsgID="201904051632015"></Routing>
<MVRRecLoop>
<CLoop>
<CRec>
<C_MVRNumberAddr>ROMAN GENERAL</C_MVRNumberAddr>
</CRec>
<CRec>
<C_MVRNumberAddr>ROMAN ST</C_MVRNumberAddr>
</CRec>
<CRec>
<C_MVRNumberAddr>ROMAN CITY, ROME 111111</C_MVRNumberAddr>
</CRec>
</CLoop>
<HIJLoop>
<JRec>
<J_SVCDesc>MVR RECORD CLEAR</J_SVCDesc>
</JRec>
</HIJLoop>
</MVRRecLoop>
</MVRCHPINFF_1.0>')
from dual
)
select x.j_svcdesc, x.xmldetails
from mvr_dtl m
cross join xmltable (
'/MVRCHPINFF_1.0/MVRRecLoop'
passing xmltype(m.vendor_xml)
columns J_SVCDesc varchar2(50) path 'HIJLoop/JRec/J_SVCDesc',
xmldetails varchar2(200) path 'string-join(CLoop/CRec/C_MVRNumberAddr, "|")'
) x;
J_SVCDESC XMLDETAILS
-------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MVR RECORD CLEAR ROMAN GENERAL|ROMAN ST|ROMAN CITY, ROME 111111
如果 HIJLoop 节点名称表明也可能有多个 JRec 值,那么您也可以将它们连接起来:
columns J_SVCDesc varchar2(50) path 'string-join(HIJLoop/JRec/J_SVCDesc, "|")',
xmldetails varchar2(200) path 'string-join(CLoop/CRec/C_MVRNumberAddr, "|")'
这对示例 XML.
的输出没有影响顺便说一句,你的第二次尝试成功了;它没有错误,但也没有得到正确的结果。你传递的 address
是一个只有兄弟节点的 XML 片段,而字符串连接只看到一个值,由那些 text()
组成(我认为......类似的东西).如果您改为向下传递 CLoop 并展开第二个 XPath,那么它会起作用:
select x1.j_svcdesc, x2.xmldetails
from mvr_dtl m
cross join xmltable (
'/MVRCHPINFF_1.0/MVRRecLoop'
passing xmltype(m.vendor_xml)
columns J_SVCDesc varchar(50) path 'HIJLoop/JRec/J_SVCDesc',
HIJLoop xmltype path 'CLoop'
) x1
cross join xmltable (
'string-join(CLoop/CRec/C_MVRNumberAddr, "|")'
passing x1.HIJLoop
columns xmldetails varchar2(200) path '.'
) x2;
但是如果你真的得到 "ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence" 那么我怀疑你的数据实际上有多个 JRec 节点;在这种情况下,请参阅上面的第二个查询。
db<>fiddle 显示了这种方法和我的第一个查询的问题;它与我的第二个查询一起使用。所以你可能需要使用它:
select x.j_svcdesc, x.xmldetails
from mvr_dtl m
cross join xmltable (
'/MVRCHPINFF_1.0/MVRRecLoop'
passing xmltype(m.vendor_xml)
columns J_SVCDesc varchar2(50) path 'string-join(HIJLoop/JRec/J_SVCDesc, "|")',
xmldetails varchar2(200) path 'string-join(CLoop/CRec/C_MVRNumberAddr, "|")'
) x;
您可能还需要增加返回的列大小。