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

Posted

技术标签:

【中文标题】如何使用游标和批量收集填充嵌套表(带有嵌套对象)【英文标题】:How to populate nested table (with nested objects) by using cursor and bulk collect 【发布时间】:2019-01-04 00:02:45 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:

不匹配很明显:您的光标位于一组具有两列的行上,类型分别为VARCHAR2T_MONEY,但嵌套表需要T_WALLET 类型的对象。不知何故,您必须从游标中的数据构造T_WALLET 类型的对象。

假设您的游标定义中的SELECT 语句模拟具有两列的实际表,您可以将其包装在使用构造函数的外部查询中。 (否则表或SELECT 语句必须已经存储或创建T_WALLETs。)

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.

【讨论】:

以上是关于如何使用游标和批量收集填充嵌套表(带有嵌套对象)的主要内容,如果未能解决你的问题,请参考以下文章

在同一个嵌套表上批量收集两次

为啥批量收集到子句限制了 pl/sql 中嵌套表的大小

将数据从 ref 游标提取到嵌套表中时出现不一致的数据类型错误

带有参数化游标的嵌套 for 循环正在插入重复记录

如何在oracle中使用嵌套游标遍历同一张表[关闭]

使用带有 Rails 的改革 gem,我如何填充 has_many :通过嵌套模型