ORA-19279: XPTY0004 - XQuery 动态类型不匹配:预期的单例序列

fsc*_*aum 4 xml sql oracle oracle11g

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

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

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

<Qualitaetsbericht>
    <Organisationseinheiten_Fachabteilungen>
         <Organisationseinheiten_Fachabteilung>
               <Fachabteilungsschluessel>
               <Prozeduren>
                  <Freiwillig>
                  <Verpflichtend>
                      <Prozedur>
                         <OPS_301>
                         <Anzahl>
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

但是还有一个额外的元素可以发生

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

我想通了

<Fachabteilungsschluessel> 
Run Code Online (Sandbox Code Playgroud)

承担这种结构

<Fachabteilungsschluessel>
   <FA_Schluessel>
Run Code Online (Sandbox Code Playgroud)

或者

<Fachabteilungsschluessel>
   <Sonstiger>
       <FA_Sonstiger_Schluessel>
Run Code Online (Sandbox Code Playgroud)

每当

<Fachabteilungsschluessel>
   <Sonstiger>
       <FA_Sonstiger_Schluessel>
Run Code Online (Sandbox Code Playgroud)

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

ORA-19279: XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence - got multi-item sequence
Run Code Online (Sandbox Code Playgroud)

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

示例文件在这里:
文件

Ale*_*ole 5

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

在您的 XMLQuery 中,您从Prozedur节点开始,然后引用结构以找到 find ../../../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
)
...
Run Code Online (Sandbox Code Playgroud)

尽管其中不需要单独的 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
/
Run Code Online (Sandbox Code Playgroud)

与您的示例数据文件得到:

        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                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
...
Run Code Online (Sandbox Code Playgroud)

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

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

如果您有另一个重复节点,您可以将其提取为另一个 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
Run Code Online (Sandbox Code Playgroud)

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

但是,当您添加更多交叉连接时,性能可能会开始受到影响。