我是使用Oracle的xml DB的新手,我开始了解它,但是有一件重要的事情我无法确定:我需要确定 1.如果一个元素存在 2.如果为空
不幸的是XMLExists()只是混合了两个答案。
查询的一小部分:
SELECT case when XMLEXISTS('/' passing by ref c3.CLASS) then 1 else 0 end E_CLASS,
c3.CLASS
FROM XML_TEST x,
XMLTABLE ('/Data/EMPLOYER'
PASSING x.File_XML
COLUMNS DOSSIER NUMBER(8) PATH 'DOSSIER',
SUMMARY XMLTYPE PATH 'SUMMARY'
) e,
XMLTABLE ('/SUMMARY'
PASSING e.SUMMARY
COLUMNS BEGINDATE DATE PATH 'BEGINDATE',
WORKER XMLTYPE PATH 'WORKER'
) c1,
XMLTABLE ('/WORKER'
PASSING c1.WORKER
COLUMNS NRWORKER NUMBER(7) PATH 'NRWORKER',
RESULT_DETAIL XMLTYPE PATH 'RESULT_DETAIL'
) c2 ,
XMLTABLE ('/RESULT_DETAIL'
PASSING c2.RESULT_DETAIL
COLUMNS CODE CHAR(5) PATH 'CODE',
MINUTES NUMBER(5) PATH 'MINUTES',
CLASS CHAR(1) PATH 'CLASS'
) c3 ;
答案 0 :(得分:0)
XMLEXISTS
确实为空元素返回true,您只是向其发送c3.CLASS
,它是CHAR(1)
列而不是XMLTYPE
,因此它没有检测根元素(/
)并返回false。
这是您可以使用此方法的不同示例。我将CLASS的XMLTYPE副本添加到c3,并在SELECT子句中引用了它。尝试从示例数据或整个CLASS节点中删除“ z”,然后看看会发生什么。
请参见how to write an XPATH query to check if a node is empty的类似问题。
-- sample data
with xml_test as (select xmltype('<Data><EMPLOYER><SUMMARY><WORKER><RESULT_DETAIL><CLASS>z</CLASS></RESULT_DETAIL></WORKER></SUMMARY></EMPLOYER></Data>') as file_xml from dual)
-- your query
SELECT --case when XMLEXISTS('/' passing by ref c3.class) then 1 else 0 end E_CLASS, /* won't work if CLASS is non-empty */
case when XMLEXISTS('/' passing by ref c3.class_x) then 1 else 0 end E_CLASS_X,
case when XMLEXISTS('/RESULT_DETAIL/CLASS' passing by ref c2.RESULT_DETAIL) then 1 else 0 end E_RD_CLASS,
c3.CLASS,
c3.CLASS_X,
-- but this probably does what you want, detect if CLASS exists and is empty:
case when XMLEXISTS('/CLASS' passing by ref c3.class_x)
and not XMLEXISTS('/CLASS/text()' passing by ref c3.class_x) then 1 else 0 end EMPTY_CLASS
FROM XML_TEST x,
XMLTABLE ('/Data/EMPLOYER'
PASSING x.File_XML
COLUMNS DOSSIER NUMBER(8) PATH 'DOSSIER',
SUMMARY XMLTYPE PATH 'SUMMARY'
) e,
XMLTABLE ('/SUMMARY'
PASSING e.SUMMARY
COLUMNS BEGINDATE DATE PATH 'BEGINDATE',
WORKER XMLTYPE PATH 'WORKER'
) c1,
XMLTABLE ('/WORKER'
PASSING c1.WORKER
COLUMNS NRWORKER NUMBER(7) PATH 'NRWORKER',
RESULT_DETAIL XMLTYPE PATH 'RESULT_DETAIL'
) c2 ,
XMLTABLE ('/RESULT_DETAIL'
PASSING c2.RESULT_DETAIL
COLUMNS CODE CHAR(5) PATH 'CODE',
MINUTES NUMBER(5) PATH 'MINUTES',
CLASS CHAR(1) PATH 'CLASS',
CLASS_X XMLTYPE PATH 'CLASS' -- added an XMLTYPE column with the same data
) c3 ;
答案 1 :(得分:0)
您可以使用//[not(text())][not(*)]
至find elements without any text and without children。
因此,在您的上下文中,您可以使用:
CASE
WHEN c2.RESULT_DETAIL IS NULL
OR
XMLEXISTS(
'/RESULT_DETAIL/CLASS[not(text())][not(*)]'
PASSING c2.RESULT_DETAIL
)
THEN 1
ELSE 0
END AS isClassEmpty
您还可以LEFT OUTER JOIN
您的表,以便仍然出现缺少的元素,然后可以测试CLASS
的值是否为NULL
:
Oracle设置:
CREATE TABLE XML_TEST ( File_XML ) AS
SELECT XMLTYPE( '<Data>
<EMPLOYER>
<DOSSIER>1</DOSSIER>
<SUMMARY>
<BEGINDATE>2019-02-13</BEGINDATE>
<WORKER>
<NRWORKER>42</NRWORKER>
<RESULT_DETAIL>
<CODE>12345</CODE>
<MINUTES>0</MINUTES>
<CLASS></CLASS>
</RESULT_DETAIL>
</WORKER>
</SUMMARY>
</EMPLOYER>
</Data>' ) FROM DUAL UNION ALL
SELECT XMLTYPE( '<Data>
<EMPLOYER>
<DOSSIER>2</DOSSIER>
<SUMMARY>
<BEGINDATE>2019-02-14</BEGINDATE>
<WORKER>
<NRWORKER>1</NRWORKER>
<RESULT_DETAIL>
<CODE>98765</CODE>
<MINUTES>600</MINUTES>
<CLASS>B</CLASS>
</RESULT_DETAIL>
</WORKER>
</SUMMARY>
</EMPLOYER>
</Data>' ) FROM DUAL UNION ALL
SELECT XMLTYPE( '<Data>
<EMPLOYER>
<DOSSIER>3</DOSSIER>
<SUMMARY>
<BEGINDATE>2019-02-14</BEGINDATE>
<WORKER>
<NRWORKER>7</NRWORKER>
</WORKER>
</SUMMARY>
</EMPLOYER>
</Data>' ) FROM DUAL
查询:
SELECT Dossier,
BeginDate,
NRWorker,
Code,
Minutes,
Class,
CASE
WHEN c2.RESULT_DETAIL IS NULL
OR
XMLEXISTS(
'/RESULT_DETAIL/CLASS[not(text())][not(*)]'
PASSING c2.RESULT_DETAIL
)
THEN 1
ELSE 0
END AS isClassEmpty,
CASE WHEN Class IS NULL THEN 1 ELSE 0 END AS isClassEmpty2
FROM XML_TEST x
LEFT OUTER JOIN
XMLTABLE(
'/Data/EMPLOYER'
PASSING x.File_XML
COLUMNS DOSSIER NUMBER(8) PATH 'DOSSIER',
SUMMARY XMLTYPE PATH 'SUMMARY'
) e
ON ( 1 = 1 )
LEFT OUTER JOIN
XMLTABLE(
'/SUMMARY'
PASSING e.SUMMARY
COLUMNS BEGINDATE DATE PATH 'BEGINDATE',
WORKER XMLTYPE PATH 'WORKER'
) c1
ON ( 1 = 1 )
LEFT OUTER JOIN
XMLTABLE(
'/WORKER'
PASSING c1.WORKER
COLUMNS NRWORKER NUMBER(7) PATH 'NRWORKER',
RESULT_DETAIL XMLTYPE PATH 'RESULT_DETAIL'
) c2
ON ( 1 = 1 )
LEFT OUTER JOIN
XMLTABLE(
'/RESULT_DETAIL'
PASSING c2.RESULT_DETAIL
COLUMNS CODE CHAR(5) PATH 'CODE',
MINUTES NUMBER(5) PATH 'MINUTES',
CLASS CHAR(1) PATH 'CLASS'
) c3
ON ( 1 = 1 );
输出:
DOSSIER | BEGINDATE | NRWORKER | CODE | MINUTES | CLASS | ISCLASSEMPTY | ISCLASSEMPTY2 ------: | :-------- | -------: | :---- | ------: | :---- | -----------: | ------------: 1 | 13-FEB-19 | 42 | 12345 | 0 | null | 1 | 1 2 | 14-FEB-19 | 1 | 98765 | 600 | B | 0 | 0 3 | 14-FEB-19 | 7 | null | null | null | 1 | 1
db <>提琴here