当 XPath 不存在时,Oracle XMLTABLE 左外连接不会 return 结果

Oracle XMLTABLE left outer join doesn't return results when XPath doesn't exist

table tbl 有一个类型为 XMLTYPE 的列 xml_data。 考虑以下 XML:

<root>
  <element>
    <id>1</id>
    <data>abc</data>
  </element>
  <element>
    <id>2</id>
    <data>def</data>
  </element>
</root>

我需要一个 select 语句,它将 return tbl 中每一行的 1 行,有 3 列:id1、id2 和 id3。

id1将从"id"为1的"element"节点中获取"data"标签的值,id2将从"id"为2的节点中获取值,依此类推

如果某个 id 没有元素(如上面 XML 中的 id3),NULL 将在该列中 returned。

所以对于上面的XML我想得到

id1 id2 id3
abc def -

我试过:

SELECT id1.val, id2.val, id3.val
  FROM tbl t,
       XMLTable('/root/element[id=1]' 
                PASSING t.xml_data 
                COLUMNS val VARCHAR2(100) PATH 'data') id1,
       XMLTable('/root/element[id=2]' 
                PASSING t.xml_data 
                COLUMNS val VARCHAR2(100) PATH 'data') id2,
       XMLTable('/root/element[id=3]' 
                PASSING t.xml_data 
                COLUMNS val VARCHAR2(100) PATH 'data') id3;

但我得到 0 行,因为没有 '/root/element[id=3]'.

我尝试添加 (+):

XMLTable ('/root/element[id=3]'
          PASSING t.xml_data
          COLUMNS val VARCHAR2 (100) PATH 'data') (+) id3;

它没有帮助(LEFT OUTER JOIN with ON 1=1)。

我注意到如果 XML 查询有效但 xmltable 中的“路径”不存在,它 确实 工作并且 NULL 被 returned(即使没有 (+) ),但是如果 XQuery 本身不存在 [id=3] 它就不起作用。

SELECT id1.val, id2.val, id3.val
  FROM tbl t,
       XMLTable('/root/element[id=1]' 
                PASSING t.xml_data 
                COLUMNS val VARCHAR2(100) PATH 'data') id1,
       XMLTable('/root/element[id=2]' 
                PASSING t.xml_data 
                COLUMNS val VARCHAR2(100) PATH 'data') id2,
       XMLTable('/root/element[id=2]' 
                PASSING t.xml_data 
                COLUMNS val VARCHAR2(100) PATH 'doesnt-exist') id3;

Returns:

id1 id2 id3
abc def -

不需要多次调用XMLTable,可以将元素选择移到列路径子句中,这样的子句有3个:

select x.id1, x.id2, x.id3
from tbl t
cross join
  xmltable ('/root'
    passing t.xml_data
    columns id1 varchar2 (100) path 'element[id=1]/data',
       id2 varchar2 (100) path 'element[id=2]/data',
       id3 varchar2 (100) path 'element[id=3]/data'
) x;

ID1   ID2   ID3 
----- ----- -----
abc   def        

希望对您有所帮助

WITH TEMP AS(
SELECT ID,DATA_VALUE
  FROM XMLTABLE('./root/element' PASSING XMLTYPE('<root>
  <element>
    <id>1</id>
    <data>abc</data>
  </element>
  <element>
    <id>2</id>
    <data>def</data>
  </element>
</root>')
COLUMNS ID NUMBER PATH './id',
        DATA_VALUE VARCHAR2(240) PATH './data'))
SELECT (SELECT DATA_VALUE FROM TEMP WHERE ID = 1) ID1, 
      (SELECT DATA_VALUE FROM TEMP WHERE ID = 2) ID2,
      (SELECT DATA_VALUE FROM TEMP WHERE ID = 3) ID3
  FROM DUAL;