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

时间:2016-03-01 12:35:49

标签: xml oracle xpath left-join xmltable

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

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

我需要一个select语句,它将为tbl中的每一行返回1行,包含3列:id1,id2&amp; ID3。

id1将从“element”节点获取“data”标签的值,其中“id”为1. id2将从“id”为2的节点获取值,等等。

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

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

   id1    id2    id3
   --------------------
1  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 ON ON 1 = 1)。

我注意到如果XMLQuery有效但xmltable中的“路径”不存在,则 DOES 工作并返回NULL(即使没有(+)),但如果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;

返回:

   id1    id2    id3
   --------------------
1  abc    def    -

2 个答案:

答案 0 :(得分:1)

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

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        

答案 1 :(得分:0)

希望这有帮助

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;