ORA-19279 XPTY0004 - Несовпадение динамических типов в Xquery: ожидаемая одноэлементная последовательность - получена многоэлементная последовательность
У меня есть следующее ниже XML-сообщение в столбце CLOB:
<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
<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 один раз указан тег конфиденциальности xml, ошибка не возникает.
1 ответ
В зависимости от того, что вы хотите сделать, когда есть только узел 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)
получает тип значения из значения типа 'low' (согласно сравнению строк); это означает, что он устанавливает приоритет над C, а не M, если оба существуют, но будет использовать любой, если есть только один