ORA-19279 XPTY0004 - Xquery 动态类型不匹配:预期的单例序列 - 得到多项序列

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

我在 CLOB 列中有下面 xml 消息:

<Message type="Close Subscription" creationdatetime="15/01/2010 07:48" market="01" xmlns="http://test.org/">
  <Customer userId="data" market="01">
    <UserAccount>test@hotmail.com</UserAccount>
    <ExpireDate>15/02/2016 07:48:11</ExpireDate>
    <Member>
      <MemberReferency number="000003" digit="85" market="01" name="John Rambo"/>
    </Member>
    <Email Id="700">
      <Address>test@hotmail.com</Address>
      <IsConfirmed>True</IsConfirmed>
      <Privacies>
        <Privacy type="C" value="I"/>
        <Privacy type="M" value="I"/>
      </Privacies>
    </Email>
    <Newsletter mailService="NL">
      <language>N</language>
      <frequency>0</frequency>
      <promotion/>
      <origin/>
    </Newsletter>
  </Customer>
</Message>

对于这条 xml 消息,我有两倍的 xml 标签 privacy

  <Privacies>
    <Privacy type="C" value="I"/>
    <Privacy type="M" value="T"/>
  </Privacies>

如何在不获取错误的情况下仅获取其中一个的隐私值?

我的意思是,获取类型的隐私='C'。

现在我正在使用包含错误的下一个查询:

select Privacy
  from (select *
          from ta_gen.notification_log a,
               XMLTable(XMLNAMESPACES('http://test.org/' AS "XML"),
                        '/XML:Message' passing xmltype(NTL_MSG) columns                            
                        Privacy VARCHAR2(1)     path 'XML:Customer/XML:Email/XML:Privacies/XML:Privacy/@value') O
         where a.ntl_type = 'Message')

注意:当 xml 标签 privacy 在 xml 消息中出现一次时,不会引发错误。

根据您希望在只有 M 型节点时发生的情况,您可以显式搜索类型属性 C:

select x.privacy
from notification_log a
cross join XMLTable(XMLNamespaces('http://test.org/' AS "XML"),
  '/XML:Message'
  passing XMLType(ntl_msg)
  columns privacy varchar2(1)
    path 'XML:Customer/XML:Email/XML:Privacies/XML:Privacy[@type="C"]/@value') x
where a.ntl_type = 'Message';

PRIVACY
-------
I

或者您可以通过二级 XMLTable 提取所有隐私节点的类型和值,然后决定保留哪个:

select min(x2.privacy) keep (dense_rank first order by x2.type) as privacy
from notification_log a
cross join XMLTable(XMLNamespaces('http://test.org/' AS "XML"),
  '/XML:Message' passing XMLType(ntl_msg)
  columns privacies XMLType path 'XML:Customer/XML:Email/XML:Privacies') x1
cross join XMLTable(XMLNAMESPACES('http://test.org/' AS "XML"),
  'XML:Privacies/XML:Privacy'
  passing privacies
  columns type varchar2(1) path '@type',
    privacy varchar2(1) path '@value') x2
where a.ntl_type = 'Message';

PRIVACY
-------
I      

如果您 运行 执行相同的查询但执行了 select x2.type, x2.value from ... 那么您会看到:

TYPE PRIVACY
---- -------
C    I      
M    I      

..而min(x2.privacy) keep (dense_rank first order by x2.type)从'lower'(根据字符串比较)类型值中获取值类型;这意味着如果 C 和 M 都存在,它将优先于 M,但如果只有一个,则将使用其中一个