PL / SQL: как просмотреть результаты sql extract () - PullRequest
2 голосов
/ 30 августа 2011

Это произвольный пример.Это реальная проблема, но я не могу поделиться реальным кодом.

У меня есть строка XML, которая не имеет стандартизированных имен узлов.пример:

<row>
  <date name="date1" id="101"></date>
  <element1 name="ele1" id="111">
    <stuff></stuff>
    <stuff></stuff>
    <stuff></stuff>
  </element1>
  <element2 name="ele2" id="121">
  </element2>
  ...
  <element15 name="ele15" id="1151></element15>
</row>

у некоторых узлов элементов есть дочерние элементы, у некоторых - нет.

Этот xml содержится в таблице базы данных (для аргумента ради: table1, column1).

Мне нужно перебрать этот код, используя pl / sql, чтобы получить: 1. атрибут nameполе даты 2. атрибут id поля даты 3. атрибут name первого узла после даты 4. атрибут id первого узла после даты 5. атрибут name второго узла после даты 6.атрибут id второго узла после даты

Мне нужно сделать это для первых 4 (произвольных) строк (sql-запросы имеют rownum <5) </p>

Пока я пыталсячтобы получить данные с помощью

set serveroutput on format word_wrapped;
DECLARE

    x_att_name varchar2(4000);
    x_id varchar2(4000);
    x_oth_name varchar2(4000);
    x_oth_id varchar2(4000);
    aCount number := 1;
    xpath1 varchar2(4000);
    xpath2 varchar2(4000);

BEGIN

    FOR i IN  (
                  SELECT 

                  EXTRACT(column1, '/row/date/@name') as att_name,
                  EXTRACT(column1, '/row/date/@id') as id,
                  EXTRACT(column1, '/row/date/following::*/@name') as other_name,
                  EXTRACT(column1, '/row/date/following::*/@id') as other_id

                  FROM table1
                  WHERE column1is not null and rownum < 5
              )
    LOOP

            x_att_name := i.att_name.getStringVal();
            x_id := i.id.getStringVal();
            x_oth_name := i.other_name.getStringVal();
            x_oth_id := i.other_id.getStringVal();

            dbms_output.put_line('LOOPS: ' || aCount);
            dbms_output.put_line(' DATE: ' || x_att_name);
            dbms_output.put_line(' PKDATE: ' || x_id);
            dbms_output.put_line(' FLDNAME: ' || x_oth_name);
            dbms_output.put_line(' PKFLD: ' || x_oth_id);

            aCount := aCount+1;

    END LOOP;

END;

Когда я запускаю это, я получаю:

anonymous block completed
LOOPS: 1
 DATE: date1
 PKDATE: 101
 FLDNAME: ele1ele2ele3ele4...ele15
 PKFLD: 111121131141...1151
....

Таким образом, он по существу выплевывает все атрибуты имени от остальных узлов в этой записи базы данныхвместе (а не в списке, как я надеялся).

Он делает то же самое для идентификаторов.

Важно отметить: - все узлы элементов имеют широко варьирующиеся атрибуты имен.Это не просто список трехсимвольных строк с числами, добавленными в конце (ele1);- все атрибуты id для каждого узла сильно различаются.Они представляют собой беспорядочную строку чисел (например, 10212), они не идут в порядке asc / dsc, не являются последовательными и не связаны никаким шаблоном.

Очевидно, что я не могу просто перебрать всеузлов элементов, так как они все уникальны.Я не могу понять, как написать xpath, чтобы получить «все узлы после этого».

Я новичок в pl / sql и изучил все, что вы видите здесь, всего за несколько днейпоэтому очевидно, что более сложные / тонкие моменты языка все еще ускользают от меня.

Любая помощь, которую вы можете предложить, будет принята с благодарностью.Если я сделал какие-либо опечатки или был неясен каким-либо образом, пожалуйста, дайте мне знать, чтобы я мог уточнить.

Спасибо Q

1 Ответ

0 голосов
/ 01 сентября 2011

Вы ищете XMLTABLE .

create table so10t(
  id number,
  data xmltype
);

insert into so10t values (1, xmltype(
'<row>
  <date name="date1" id="101"></date>
  <element1 name="ele1" id="111">
    <stuff></stuff>
    <stuff></stuff>
    <stuff></stuff>
  </element1>
  <element2 name="ele2" id="121">
  </element2>
  <element15 name="ele15" id="1151"></element15>
</row>'));
insert into so10t values (2, xmltype(
'<row>
  <date name="date2" id ="102"/>
  <elem23 name="ele23" id="201">
    <whatever/>
  </elem23>
  <elem56 name="ele56" id="402"/>
  <elem112 name="ele112" id="804"/>
</row>'));

declare
  type rec_t is record(
    date_name varchar2(10),
    date_id number,
    first_elem_name varchar2(10),
    first_elem_id number,
    second_elem_name varchar2(10),
    second_elem_id number
  );
  rec rec_t;
  cur sys_refcursor;
begin
  open cur for
    select x.*
      from so10t,
      xmltable('row' passing so10t.data
               columns
               /* 1. the name attribute of the date field */
               date_name varchar2(10) path 'date/@name',
               /* 2. the id attribute of the date field */
               date_id number path 'date/@id',
               /* 3. the name attribute of the first node after the date */
               first_elem_name varchar2(10) path 'date/(following::*)[1]/@name',
               /* 4. the id attribute of the first node after the date */
               first_elem_id number path 'date/(following::*)[1]/@id',
               /* 5. the name attribute of the second node after the date */
               second_elem_name varchar2(10) path 'date/(following::*)[1]/(following::*)[1]/@name',
               /* 6. the id attribute of the second node after the date */
               second_elem_id number path 'date/(following::*)[1]/(following::*)[1]/@id'
               ) x 
      where rownum < 5 ;

  fetch cur into rec;
  while cur%found loop
    dbms_output.put_line(rec.date_name || ';' || rec.date_id || ';' ||
                         rec.first_elem_name || ';' || rec.first_elem_id || ';' ||
                         rec.second_elem_name || ';' || rec.second_elem_id);
    fetch cur into rec;
  end loop;

  close cur;
end;
/
...