Oracle многоуровневая коллекция в PL / SQL

У меня есть многоуровневая коллекция, описанная ниже.

declare
     type t_addr_lines is varray(4) of varchar2(60);
     type t_addr_entry is table of t_addr_lines index by varchar2(10);
     type t_student    is record
     (
         last_name      varchar2(20),
         first_name     varchar2(20),
         l_addr_entry   t_addr_entry
     );

     type t_students is table of t_student; 

     l_students t_students;

     begin

         l_students := t_students();
         l_students.extend();

     end;

/

По сути структура является:

 a. a student can have different types of addresses ( 'HOME', 'VACATION' )
 b. each address can have maximum of 4 lines

Я задаюсь вопросом, как обратиться и заполнить различные компоненты коллекции.

Всего 1 ответ


Вы смешиваете несколько типов коллекций, так что это немного грязно, но я думаю, в этом суть. Вы можете ссылаться на каждую запись в вашей структуре varray либо по ее позиции (число), либо используя first / last; Затем вы непосредственно назначаете элементам записи:

begin
  l_students := t_students();

  l_students.extend();
  -- explicit carray entry number 
  l_students(1).first_name := 'Bruce'
  l_students(1).last_name := 'Wayne'
  l_students(1).l_addr_entry('Home') := t_addr_lines(񟝟 Mountain Drive', 'Gotham');
  l_students(1).l_addr_entry('Work') := t_addr_lines('The Batcave', 񟝟 Mountain Drive', 'Gotham');

Для адресных записей вы указываете, какую запись вы назначаете, используя в качестве ключа значение из 10 символов, например, Дом или Работа. Затем вы назначаете новый экземпляр таблицы t_addr_lines , заполненный до для строк.

А затем, для второго ученика, расширьте и снова заполните:

  l_students.extend();
  -- last entry in varray
  l_students(l_students.last).first_name := 'Clark'
  l_students(l_students.last).last_name := 'Kent'
  l_students(l_students.last).l_addr_entry('Work') := t_addr_lines('The Daily Planet', 'Metropolis');

Чтобы вернуть данные, вы можете l_students записи l_students :

  for i_stud in l_students.first..l_students.last
  loop
    ...
  end loop;

Адреса немного сложнее, особенно если вы хотите узнать значение ключа. Вам нужно получить первое значение ключа и присвоить его переменной, которую вы должны были объявить ранее:

   i_addr := l_students(i_stud).l_addr_entry.first;

а затем цикл, увеличивая значение этого ключа:

    loop
      ...
      i_addr := l_students(i_stud).l_addr_entry.next(i_addr);
    end loop;

Затем в этом цикле (!), Еще один цикл над адресными строками этой записи:

      for i_line in l_students(i_stud).l_addr_entry(i_addr).first
                  ..l_students(i_stud).l_addr_entry(i_addr).last
      loop
        ...
      end loop;

Итак, собрав это вместе и просто dbms_output значения с помощью dbms_output :

declare
  type t_addr_lines is varray(4) of varchar2(60);
  type t_addr_entry is table of t_addr_lines index by varchar2(10);

  type t_student    is record
  (
    last_name      varchar2(20),
    first_name     varchar2(20),
    l_addr_entry   t_addr_entry
  );

  type t_students is table of t_student; 

  l_students t_students;

  -- index for address entries
  i_addr varchar2(10);

begin
  l_students := t_students();

  l_students.extend();
  -- explicit carray entry number 
  l_students(1).first_name := 'Bruce'
  l_students(1).last_name := 'Wayne'
  l_students(1).l_addr_entry('Home') := t_addr_lines(񟝟 Mountain Drive', 'Gotham');
  l_students(1).l_addr_entry('Work') := t_addr_lines('The Batcave', 񟝟 Mountain Drive', 'Gotham');

  l_students.extend();
  -- last entry in varray
  l_students(l_students.last).first_name := 'Clark'
  l_students(l_students.last).last_name := 'Kent'
  l_students(l_students.last).l_addr_entry('Work') := t_addr_lines('The Daily Planet', 'Metropolis');

  for i_stud in l_students.first..l_students.last
  loop
    dbms_output.put_line('Student: '
      || l_students(i_stud).last_name ||', '|| l_students(i_stud).first_name);

    -- get index value of first address table entry
    i_addr := l_students(i_stud).l_addr_entry.first;
    -- loop over addresses starting from that index
    while i_addr is not null
    loop
      dbms_output.put_line('Address (' || i_addr || '):');
      -- loop over lines in this address
      for i_line in l_students(i_stud).l_addr_entry(i_addr).first
                  ..l_students(i_stud).l_addr_entry(i_addr).last
      loop
        dbms_output.put_line('  ' || l_students(i_stud).l_addr_entry(i_addr)(i_line));
      end loop;
      i_addr := l_students(i_stud).l_addr_entry.next(i_addr);
    end loop;
  end loop;
end;
/

который получает:

Student: Wayne, Bruce
Address (Home):
  1007 Mountain Drive
  Gotham
Address (Work):
  The Batcave
  1007 Mountain Drive
  Gotham
Student: Kent, Clark
Address (Work):
  The Daily Planet
  Metropolis


PL/SQL procedure successfully completed.

дб <> скрипка


Есть идеи?

10000