如何使用光标和批量收集来填充嵌套表(带有嵌套对象)

时间:2019-01-04 00:02:46

标签: oracle plsql type-mismatch

也许您知道问题出在哪里。

我有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;

Aaaaaaand ...不起作用。我收到此错误:

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脚本     https://livesql.oracle.com/apex/livesql/s/hr22zxdw7842um41u9ylnraz1

1 个答案:

答案 0 :(得分:1)

不匹配很明显:您的光标位于具有两列的一组行上,分别为VARCHAR2T_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.