【问题标题】:ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequenceORA-19279: XPTY0004 - XQuery 动态类型不匹配:预期的单例序列
【发布时间】:2017-07-12 12:12:22
【问题描述】:

我对 XML 很陌生,我希望在这里列出所有相关信息。如果没有,请不要发送负面反馈。如果您让我知道您缺少哪些信息,我将不胜感激。

我未能在 Oracle 数据库 11g 的 XML 视图中的多个元素上正常运行以下查询。

我有多个 XML 文件,其结构如下:

<Qualitaetsbericht>
    <Organisationseinheiten_Fachabteilungen>
         <Organisationseinheiten_Fachabteilung>
               <Fachabteilungsschluessel>
               <Prozeduren>
                  <Freiwillig>
                  <Verpflichtend>
                      <Prozedur>
                         <OPS_301>
                         <Anzahl>

我通常通过以下查询得到正确的结果:

SELECT id, 
       d."FA_SCHLUESSEL",d."OPS_301",
       CASE WHEN d."ANZAHL" IS NULL THEN '4' ELSE d."ANZAHL" END AS ANZAHL,
       d."GLIEDERUNGSNUMMER",d."NAME"
FROM   XMLDocs x,
XMLTable(
'/Data'
PASSING XMLQuery(
'for $i in /Qualitaetsbericht./Organisationseinheiten_Fachabteilungen/Organisationseinheit_Fachabteilung/Prozeduren/Verpflichtend/Prozedur
return <Data>
                 {$i/OPS_301}
                 {$i/Anzahl}
                 {$i/../../../Fachabteilungsschluessel/FA_Schluessel}
                 {$i/../../../Gliederungsnummer}
{$i/../../../Name}
</Data>'
PASSING doc
RETURNING CONTENT
)
COLUMNS FA_Schluessel varchar2(12) path 'FA_Schluessel',
        OPS_301      varchar2(12) path 'OPS_301',
        Anzahl        varchar2(40) path 'Anzahl',
        Gliederungsnummer varchar2(10) path 'Gliederungsnummer',
        Name varchar2(600) path 'Name'
) d

但是还有一个额外的元素可以出现

如果在 XML 中给出了这个元素,我上面的查询会遇到动态类型不匹配错误。

我发现了

<Fachabteilungsschluessel> 

具有这种结构

<Fachabteilungsschluessel>
   <FA_Schluessel>

<Fachabteilungsschluessel>
   <Sonstiger>
       <FA_Sonstiger_Schluessel>

无论何时

<Fachabteilungsschluessel>
   <Sonstiger>
       <FA_Sonstiger_Schluessel>

出现在XML文档中我得到错误代码:

ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence

我希望这是一个容易解决的问题。目前我的想法已经不多了。有人可以帮忙吗? -提前致谢。

此处的示例文件:
file

【问题讨论】:

  • 显示问题的正确示例 XML 将有所帮助(尽可能小,并且对真实数据进行混淆处理很好),以及您期望从该特定文档获得的输出。目前您显示的轮廓与 XPath 不匹配,并且似乎没有重复的节点,这就是错误的真正含义。顺便说一句,你为什么要在 XMLTable 中做一个单独的 XMLQuery?
  • 嗨,亚历克斯,我已经编辑了帖子。您现在可以下载示例文件。我需要的金额的嵌套信息,即“FA_Schluessel”或“FA_Sonstiger_Schluessel”。在我的观点中,我看不到另一种结合显示这些数据的可能性。但我愿意接受任何更好的解决方案。
  • 2.5MB 真的越小越好吗?
  • 这是较小的文件之一。我知道这是一种痛苦。这些文件具有不同的级别,我不确定我是否可以操纵它们以使其仍按预期工作。如果我把它缩小了,我会立即分享缩小的文件。

标签: sql xml oracle oracle11g


【解决方案1】:

问题在于重复的节点。在您的第二个 Organisationseinheit_Fachabteilung 节点(其中有 2 个 Gliederungsnummer)中有 两个 Fachabteilungsschluessel 节点,每个节点都有一个 FA_Schluessel - 0193 和 0300。

在您的 XMLQuery 中,您从 Prozedur 节点开始,然后返回结构以找到 ../../../Fachabteilungsschluessel/FA_Schluessel。在这种情况下,它会找到两个匹配项 - 即多个项目,其中一个是预期的。

您可以调整您的 XMLQuery 的 XPath 以使用嵌套循环,但它会变得有点混乱且难以理解,而且在我使用您的 2.5MB 文件进行测试时也很慢:

...
PASSING XMLQuery(
'for $i in /Qualitaetsbericht/Organisationseinheiten_Fachabteilungen/Organisationseinheit_Fachabteilung
for $j in $i/Prozeduren/Verpflichtend/Prozedur
return <Data>
                 {$j/OPS_301}
                 {$j/Anzahl}
                 {$i/Fachabteilungsschluessel/FA_Schluessel}
                 {$i/Gliederungsnummer}
                 {$i/Name}
</Data>'
PASSING doc
RETURNING CONTENT
)
...

虽然您不需要在其中使用单独的 XMLQuery,但 XMLTable 的 XPath 可以自己完成所有这些工作。

您可以改为使用多个级别的 XMLTable:

SELECT xd.id, 
       x3.fa_schluessel,
       x2.ops_301,
       CASE WHEN x2.anzahl IS NULL THEN '4' ELSE x2.anzahl END AS anzahl,
       x1.gliederungsnummer,
       x1.name
FROM   XMLDocs xd
CROSS JOIN XMLTable(
  '/Qualitaetsbericht/Organisationseinheiten_Fachabteilungen/Organisationseinheit_Fachabteilung'
  PASSING doc
  COLUMNS gliederungsnummer varchar2(10) path 'Gliederungsnummer',
          name varchar2(600) path 'Name',
          prozeduren XMLType path 'Prozeduren',
          fa_schluessel XMLType path 'Fachabteilungsschluessel/FA_Schluessel'
) x1
CROSS JOIN XMLTable(
  '/Prozeduren/Verpflichtend/Prozedur'
  PASSING x1.prozeduren
  COLUMNS ops_301 varchar2(12) path 'OPS_301',
          anzahl varchar2(40) path 'Anzahl'
) x2
CROSS JOIN XMLTable(
  '/FA_Schluessel'
  PASSING x1.fa_schluessel
  COLUMNS fa_schluessel varchar2(12) path '.'
) x3
/

与您的示例数据文件一起获得:

        ID FA_SCHLUESSE OPS_301      ANZAHL                                   GLIEDERUNG NAME                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
---------- ------------ ------------ ---------------------------------------- ---------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        42 0100         1-204.2      4                                        1          Notfallmedizin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        42 0100         1-207.0      5                                        1          Notfallmedizin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        42 0100         1-208.3      4                                        1          Notfallmedizin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        42 0100         1-208.6      4                                        1          Notfallmedizin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        42 0100         1-266.0      4                                        1          Notfallmedizin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        42 0100         1-610.2      4                                        1          Notfallmedizin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        42 0100         1-844        4                                        1          Notfallmedizin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        42 0100         3-052        5                                        1          Notfallmedizin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        42 0100         3-200        67                                       1          Notfallmedizin                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
...

第一个 XMLTable 直接获取 Organisationseinheit_Fachabteilun 节点下的数据,并且还获取每个节点的子 Prozeduren 和 'Fachabteilungsschluessel/FA_Schluessel` 片段作为单独的 XMLTypes,可以有多个节点。然后将这些片段传递给第二个和第三个 XMLTables,它们会提取较低级别的数据。

使用此模型可以有多个父节点,每个父节点都有多个子节点。

如果您有另一个重复节点,您可以将其提取为另一个 XMLType 片段,并添加第四个 XMLTable:

...
  COLUMNS gliederungsnummer varchar2(10) path 'Gliederungsnummer',
          name varchar2(600) path 'Name',
          prozeduren XMLType path 'Prozeduren',
          fa_schluessel XMLType path 'Fachabteilungsschluessel/FA_Schluessel',
          fa_sonstiger_schluessel XMLType
            path 'Fachabteilungsschluessel/Sonstiger/FA_Sonstiger_Schluessel'
) x1
...
CROSS JOIN XMLTable(
  '/FA_Sonstiger_Schluessel'
  PASSING x1.fa_sonstiger_schluessel
  COLUMNS fa_sonstiger_schluessel varchar2(12) path '.'
) x4

...然后可以在主选择列表中使用x4.fa_sonstiger_schluessel

随着您添加更多交叉连接,性能可能会开始下降。

【讨论】:

  • 嘿,亚历克斯,正确。这给了我适当的数据,直到出现 FA_Sonstiger_Schluessel 的 Level First 条目。以下是 Fachabteilungsschlüssel 在同一级别的特殊信息:“FA_Schluessel”和“/Sonstiger/FA_Sonstiger_Schluessel”。此键仍然导致错误消息。通过您的查询,问题出现在第 2054 行(WHERE ROWNUM
  • @fscherbaum - 没有出现在您的示例文件或查询中,因此不能 100% 确定,但您可能需要将第三条路径拉出到它自己的 XMLTable 中 - 完全取决于您在数据。一个 Fachabteilungsschluessel 是否可以有多个 Sonstiger;或者每个Sonstiger 可以有多个FA_Sonstiger_Schluessel - 还是两者都有?
  • @fscherbaum - 我添加了另一个级别的 XMLTable,以及如何为 Sonstiger 部分添加更多内容。如果它仍然错误,那么我认为我不理解您所描述的结构。
猜你喜欢
  • 2015-09-04
  • 1970-01-01
  • 2016-08-23
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多