XMLTABLE, XQUERY - ожидаемая одноэлементная последовательность - PullRequest
0 голосов
/ 17 апреля 2019

XML:

<import>
    <persons>
        <person>
            <pm>57924160</pm>
            <date_from>2018-05-01</date_from>
            <info>
                <set>
                    <indflag>0</indflag>
                </set>
                <items>
                    <item>
                        <symbol>a</symbol>
                        <date>2018-05-02</date>
                        <cost>190</cost>
                    </item>
                    <item>
                        <symbol>b</symbol>
                        <date>2018-05-02</date>
                        <cost>130</cost>
                    </item>
                </items>
            </info>
        </person>
    </persons>
    <persons>
        <person>
            <pm>57924160</pm>
            <date_from>2018-05-01</date_from>
            <info>
                <set>
                    <indflag>0</indflag>
                </set>
                <items>
                    <item>
                        <symbol>a</symbol>
                        <date>2018-05-02</date>
                        <cost>190</cost>
                    </item>
                    <item>
                        <symbol>b</symbol>
                        <date>2018-05-02</date>
                        <cost>130</cost>
                    </item>
                </items>
            </info>
        </person>
    </persons>
</import>

И я читаю этот XML в цикле через:

 SELECT xt.*
   FROM  XMLTABLE(
         '//import/persons/person'
         PASSING xmltype('above_xml')
         COLUMNS 
           pm        VARCHAR2(4)  PATH 'pm',
           indflag   VARCHAR2(10) PATH 'info/set/indflag'
         ) xt;

но если я добавлю еще один столбец

item      varchar2(10) PATH 'info/items/item/symbol'

это дает мне ORA, потому что xmltable ожидает 1 значение на человека, и есть два элемента на человека.

Конечно, я мог бы обработать это в pl / sql, как получить полный узел, выбрать все элементы и т. Д., Но мне интересно, можно ли это сделать в одном запросе, чтобы получить вывод вроде:

PM    INDFLAG  item
5792    0        a
5792    0        b

1 Ответ

1 голос
/ 17 апреля 2019

Вы можете использовать два уровня XMLTable:

select x1.pm, x1.indflag, x2.item
  from  xmltable(
         '//import/persons/person'
         passing xmltype('above_xml')
         columns 
           pm        varchar2(4)  path 'pm',
           indflag   varchar2(10) path 'info/set/indflag',
           items     xmltype      path 'info/items'
         ) x1
  cross join  xmltable(
         '/items/item'
         passing x1.items
         columns 
           item      varchar2(10) PATH 'symbol'
         ) x2;

PM   INDFLAG    ITEM      
---- ---------- ----------
5792 0          a         
5792 0          b         
5792 0          a         
5792 0          b         

или менее гибко, но здесь все в порядке только с одной дочерней коллекцией, начните с уровня элемента и вернитесь к данным узла более высокого уровня:

select xt.pm, xt.indflag, xt.item
  from  xmltable(
         '//import/persons/person/info/items/item'
         passing xmltype('above_xml')
         columns 
           pm        varchar2(4)  path './../../../pm',
           indflag   varchar2(10) path './../../set/indflag',
           item      varchar2(10) PATH 'symbol'
         ) xt;

PM   INDFLAG    ITEM      
---- ---------- ----------
5792 0          a         
5792 0          b         
5792 0          a         
5792 0          b         

(Второй подход не работает в 11.2.0.2 , что должно быть ошибкой; он работает в 11.2.0.4 и более поздних версиях, включая 18c .)

...