简体   繁体   English

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

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

The table tbl has a column xml_data of type XMLTYPE. 表tbl具有XMLTYPE类型的xml_data列。 Consider the following XML: 考虑以下XML:

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

I need a select statement that will return 1 row for each row in tbl, with 3 columns: id1, id2 & id3. 我需要一条select语句,该语句将为tbl中的每一行返回1行,其中包含3列:id1,id2和id3。

id1 will get the value of the "data" tag from the "element" node where the "id" is 1. id2 will get the value from the node where "id" is 2, etc. id1将从“ id”为1的“ element”节点获取“ data”标签的值。id2将从“ id”为2的节点获取值。

In case there is no element for a certain id (like id3 in the XML above), NULL will be returned in that column. 如果没有特定ID的元素(例如上述XML中的id3),则该列将返回NULL。

So for the XML above I want to get 所以对于上面的XML我想

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

I tried: 我试过了:

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;

But I get 0 rows because there is no '/root/element[id=3]'. 但是我得到0行,因为没有'/ root / element [id = 3]'。

I tried adding (+): 我尝试添加(+):

xmltable ('/root/element[id=3]'
        passing t.xml_data
        columns val varchar2 (100) path 'data') (+) id3;

It didn't help (neither LEFT OUTER JOIN with ON 1=1). 它没有帮助(ON 1 = 1的LEFT OUTER JOIN都没有)。

I noticed that if the XMLQuery is valid but the "path" inside the xmltable doesn't exist, it DOES work and NULL is returned (even without the (+) ), but if the XQuery itself doesn't exist as in [id=3] it doesn't work. 我注意到,如果XMLQuery一样有效,但“路径”的XMLTABLE内不存在,它工作并返回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;

Returns: 返回值:

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

You don't need multiple calls to XMLTable, you can move the element selection into the column path clause, and have three such clauses: 您不需要多次调用XMLTable,可以将元素选择移到列path子句中,并具有三个这样的子句:

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        

Hope this helps 希望这可以帮助

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM