【问题标题】:how to get data from different levels in a xmltable?如何从 xmltable 中的不同级别获取数据?
【发布时间】:2019-08-29 15:48:32
【问题描述】:

我正在尝试从 VENDOR_XML 列中的表 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

谁能帮我弄清楚我错过了什么。

【问题讨论】:

  • 您的第二个“我也尝试过”查询没有错误 - 无论如何都使用该示例;但没有得到完全正确的结果 - db<>fiddle.

标签: sql oracle xmltype xmltable


【解决方案1】:

您可以将字符串连接下移到列子句:

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 的输出没有影响。

db<>fiddle


顺便说一句,你的第二次尝试有点效果;它不会出错,但也不会得到正确的结果。您传递的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;

db<>fiddle

但是,如果您实际上得到“ORA-19279:XPTY0004 - XQuery 动态类型不匹配:预期的单例序列 - 得到多项序列”,那么我怀疑您的数据确实有多个 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;

您可能还需要增加返回的列大小。

【讨论】:

    猜你喜欢
    • 2023-03-28
    • 2017-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 1970-01-01
    • 2017-08-19
    • 1970-01-01
    相关资源
    最近更新 更多