sql - ORA-19279 : XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence

标签 sql xml oracle oracle11g

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

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

我有多个 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

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


如果这个 Element 在 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

最佳答案

问题在于重复的节点。在您的第二个 Organisationseinheit_Fachabteilung节点(其中有 Gliederungsnummer,共 2 个)有两个 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,可以有多个节点。然后将这些片段传递给第二个和第三个 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

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

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

关于sql - ORA-19279 : XPTY0004 - XQuery dynamic type mismatch: expected singleton sequence,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42391595/

相关文章:

sql - 使用 XQuery 在 XML 中选择除一个以外的所有节点

xml - 如何在 XML 中显示 Activity 中的整数?

java - 如何运行 Resultset.next() 两次?

sql - 如何在SQL脚本中确定LocalDb实例名称?

c# - 计算查询中的总行数

java - 如何在 Java 中获取 SoapUI 请求和响应 XML

sql - Oracle加入-常规语法VS ANSI语法之间的比较

java - 找不到 OffLine WLST 类

sql - 从相同的列但不同的条件计数

mysql - 将预定义的、可能不存在的键与表数据连接起来