[英]Referring a to generic cursor in an anonymous block in oracle
在包pkg_cost_api
中定义了以下内容。
TYPE t_ref_generic IS REF CURSOR;
以下是同一软件包中的过程。
PROCEDURE transfer_costs
(
p_source_isbn IN product_header.mhid_part_nbr%TYPE,
p_dest_isbn IN product_header.mhid_part_nbr%TYPE,
p_plant_mfg_flag IN VARCHAR2,
p_employee_number IN product_header.add_by%TYPE,
p_transfer_results OUT pkg_cost_api.t_ref_generic
) IS
v_gen_cost_rec t_gen_cost_record := t_gen_cost_record(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
v_result_set t_gen_cost_table := t_gen_cost_table();
BEGIN
-- relevant code
Loop
v_gen_cost_rec.initialize();
v_gen_cost_rec.gen_cost_code := 'some value';
v_gen_cost_rec.gen_cost_code_desc := 'some value';
v_gen_cost_rec.amount := 'some value';
v_result_set.EXTEND;
v_result_set(v_result_set.COUNT) := v_gen_cost_rec;
End Loop;
OPEN p_transfer_results FOR
SELECT *
FROM TABLE(CAST(v_result_set AS t_gen_cost_table)) gen_costs;
END;
并且类型t_gen_cost_record是:
CREATE OR REPLACE TYPE t_gen_cost_record AS
OBJECT
(
gen_cost_code VARCHAR2(30),
gen_cost_code_desc VARCHAR2(100),
amount NUMBER,
cost_code VARCHAR2(30),
acct_category_code VARCHAR2(30),
category_desc VARCHAR2(100),
category_code VARCHAR2(30),
oracle_task_code VARCHAR2(3),
MEMBER PROCEDURE initialize
);
我正在尝试在脚本下面运行它。
DECLARE
c_transfer_results pkg_cost_api.t_ref_generic;
v_finance_source_note product_note.note%TYPE;
v_comments nopc.comments%TYPE;
v_dest_comments nopc.comments%TYPE;
v_nopc_isbn nopc.isbn%TYPE := '0077449835';
v_move_plant_flag nopc.move_plant_flag%TYPE;
v_move_to_isbn nopc.move_to_isbn%TYPE := '0077364678';
v_gen_cost_code VARCHAR2(30);
v_gen_cost_code_desc VARCHAR2(100);
v_amount NUMBER;
BEGIN
pkg_cost_api.transfer_costs(
p_source_isbn => v_nopc_isbn,
p_dest_isbn => v_move_to_isbn,
p_plant_mfg_flag => 'PLANT',
p_employee_number => '000159457',
p_transfer_results => c_transfer_results
);
v_dest_comments := Chr(10) || ' Note Date: ' || SYSDATE;
v_finance_source_note := Chr(10) || ' Note Date: ' || SYSDATE;
LOOP
FETCH c_transfer_results INTO v_gen_cost_code, v_gen_cost_code_desc, v_amount;
EXIT WHEN c_transfer_results%NOTFOUND;
v_comments := v_comments || CHR(10) || 'Plant Transfer from ' || v_nopc_isbn || ' to ' || v_move_to_isbn ||
' Amounts: ' || v_gen_cost_code_desc || ': ' || v_amount || CHR(10);
v_finance_source_note := v_finance_source_note || CHR(10) || 'Plant Transfer from ' || v_nopc_isbn || ' to ' || v_move_to_isbn ||
' Amounts: ' || v_gen_cost_code_desc || ': ' || v_amount || CHR(10);
v_dest_comments := v_dest_comments || CHR(10) ||
'Plant Transfer to ' || v_move_to_isbn || ' from ' || v_nopc_isbn ||
' Amounts: ' || v_gen_cost_code_desc || ': ' || v_amount || CHR(10);
END LOOP;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;
当我尝试运行上述独立脚本时,出现以下错误:
Error report:
ORA-06504: PL/SQL: Return types of Result Set variables or query do not match
ORA-06512: at line 39 06504. 00000 - "PL/SQL: Return types of Result Set variables or query do not match"
*Cause: Number and/or types of columns in a query does not match declared return type of a result set variable, or declared types of two Result Set variables do not match.
*Action: Change the program statement or declaration. Verify what query the variable actually refers to during execution.
能否请别人告诉我我到底在做什么错。
当查询的对象类型为8时,您尝试将ref游标提取为三列。 我认为没有任何直接获取对象的方法,但是您可以定义具有与对象相同结构的本地记录类型:
DECLARE
TYPE l_gen_cost_record IS RECORD
(
gen_cost_code VARCHAR2(30),
gen_cost_code_desc VARCHAR2(100),
amount NUMBER,
cost_code VARCHAR2(30),
acct_category_code VARCHAR2(30),
category_desc VARCHAR2(100),
category_code VARCHAR2(30),
oracle_task_code VARCHAR2(3)
);
v_gen_cost_rec l_gen_cost_record;
c_transfer_results pkg_cost_api.t_ref_generic;
...
并获取:
LOOP
FETCH c_transfer_results INTO v_gen_cost_rec;
并参考该记录的字段,而不是多余的v_amount
等变量:
v_comments := v_comments || CHR(10)
|| 'Plant Transfer from ' || v_nopc_isbn
|| ' to ' || v_move_to_isbn
|| ' Amounts: ' || v_gen_cost_rec.gen_cost_code_desc
|| ': ' || v_gen_cost_rec.amount || CHR(10);
该SQL Fiddle演示程序可以编译并运行,但有一些小技巧,它们可以使用固定数据类型而不是%TYPE
变量。
将集合作为OUT变量并直接使用它可能会更简单,但这取决于在其他地方使用它。 如果您同时需要,则可以有一个用于填充集合的过程,以及一个包装器过程,该包装器过程将调用该集合并打开一个ref游标,从而为您提供灵活性。 (或流水线函数,或适合如何使用结果的任何东西)。
顺便说一句,不要抓住when others
例外的when others
。 您正在重新引发它,这是有些事情,但是您正在丢失异常的实际位置,这将使其在发生中断时更加难以调试。 仅捕获您需要处理的特定异常。
可以使用t_ref_gen_record
定义具有相同属性的本地类型,但是该匿名块需要作为过程添加到另一个包中。 因此,我要做的是在脚本中初始化了与类型相同的变量,并使用访存将transfer_costs
的out参数的值放入这些变量中。 很好。 我只使用三个变量的原因是因为在transfer_costs
过程中初始化了类型,并且其中仅三个变量被赋予了值。 我现在纠正了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.