Как заполнить вложенную таблицу (вложенными объектами) с помощью курсора и массового сбора - PullRequest
0 голосов
/ 04 января 2019

может быть, вы знаете, где проблема.

У меня есть 3 типа:

create or replace type t_money as object (
  val number(14,2)
 ,cur varchar2(3 CHAR)
);
/

create or replace type t_wallet as object (
  name   varchar2(50 CHAR)
 ,amount t_money
);
/

create or replace type t_wallets is table of t_wallet;
/

Мне нужно заполнить вложенную таблицу от курсора с помощью массового сбора:

declare
  walletCollection t_wallets;
  cursor walletCursor is 
    select 'some name'          as name
          ,t_money(99, 'EUR')   as amount
      from dual;
begin
  open walletCursor;
  fetch walletCursor bulk collect into walletCollection;
  close walletCursor;
end;

А-а-а-а-а ... это не работает.Я получаю эту ошибку:

ORA-06550: line 9, column 40: PLS-00386: type mismatch found at 'WALLETCOLLECTION' between FETCH cursor and INTO variables

Я знал, что могу использовать:

type walletRecords is table of walletCursor%ROWTYPE;
walletCollection walletRecords;

Но в этом случае я не могу этого сделать, и walletCollection должна быть вложенной таблицей t_wallets.

Как это сделать?Где несоответствие?

Oracle Live Script https://livesql.oracle.com/apex/livesql/s/hr22zxdw7842um41u9ylnraz1

1 Ответ

0 голосов
/ 04 января 2019

Несовпадение очевидно: ваш курсор находится на наборе строк с двумя столбцами типа VARCHAR2 и T_MONEY соответственно, но во вложенной таблице ожидаются объекты типа T_WALLET.Где-то, так или иначе, вы должны создать объекты типа T_WALLET из данных в курсоре.

Предполагая, что оператор SELECT в вашем определении курсора имитирует фактическую таблицу с двумя столбцами, вы можете заключить ее ввнешний запрос, где вы используете конструктор.(Или же таблица или оператор SELECT должны уже сохранять или создавать T_WALLET с.)

declare
  walletCollection t_wallets;
  cursor walletCursor is
    select t_wallet(name, amount)   -- THIS outer select, using the constructor
    from   (
             select 'some name'          as name
                  , t_money(99, 'EUR')   as amount
             from   dual
           );
begin
  open walletCursor;
  fetch walletCursor bulk collect into walletCollection;
  close walletCursor;
end;
/

Вот краткое демонстрационное руководство, показывающее, что вложенная таблица заполнена правильно.Обратите внимание на вызов dbms_output.put_line в теле процедуры;обычно вы делаете это только для целей разработки и отладки (и для иллюстрации, как в данном случае).Убедитесь, что вы запустили set serveroutput on, чтобы увидеть вывод.

declare
  walletCollection t_wallets;
  cursor walletCursor is
    select t_wallet(name, amount) 
    from   (
             select 'some name'          as name
                  , t_money(99, 'EUR')   as amount
             from   dual
           );
begin
  open walletCursor;
  fetch walletCursor bulk collect into walletCollection;
  close walletCursor;

  for i in 1 .. walletCollection.Count loop
    dbms_output.put_line( 'Name: '       || walletCollection(i).name       || 
                          ', amount: '   || walletCollection(i).amount.val ||
                          ', currency: ' || walletCollection(i).amount.cur );
  end loop;
end;
/

Name: some name, amount: 99, currency: EUR


PL/SQL procedure successfully completed.
...