如何使用游标和批量收集来填充嵌套 table(带有嵌套对象)
How to populate nested table (with nested objects) by using cursor and bulk collect
也许你知道问题出在哪里了
我有 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;
/
我需要使用批量收集从游标填充嵌套 table:
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 的嵌套 table。
怎么做?不匹配在哪里?
Oracle 实时脚本
https://livesql.oracle.com/apex/livesql/s/hr22zxdw7842um41u9ylnraz1
不匹配很明显:您的光标位于一组包含两列的行上,分别为 VARCHAR2
和 T_MONEY
类型,但嵌套的 table 需要 T_WALLET
。在某处,不知何故,您必须从游标中的数据构造 T_WALLET
类型的对象。
假设游标定义中的 SELECT
语句模拟具有两列的实际 table,您可以将其包装在使用构造函数的外部查询中。 (否则 table 或 SELECT
语句必须已经存储或创建 T_WALLET
s。)
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;
/
这里有一个简短的演示,显示嵌套的 table 已正确填充。注意过程体中对 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.
也许你知道问题出在哪里了
我有 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;
/
我需要使用批量收集从游标填充嵌套 table:
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 的嵌套 table。
怎么做?不匹配在哪里?
Oracle 实时脚本 https://livesql.oracle.com/apex/livesql/s/hr22zxdw7842um41u9ylnraz1
不匹配很明显:您的光标位于一组包含两列的行上,分别为 VARCHAR2
和 T_MONEY
类型,但嵌套的 table 需要 T_WALLET
。在某处,不知何故,您必须从游标中的数据构造 T_WALLET
类型的对象。
假设游标定义中的 SELECT
语句模拟具有两列的实际 table,您可以将其包装在使用构造函数的外部查询中。 (否则 table 或 SELECT
语句必须已经存储或创建 T_WALLET
s。)
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;
/
这里有一个简短的演示,显示嵌套的 table 已正确填充。注意过程体中对 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.