在包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.
请有人告诉我这里到底出错了什么。
答案 0 :(得分:0)
当查询中有八个来自对象类型时,您尝试将引用光标提取到三列中。我不认为有任何方法直接获取对象,但您可以定义一个与对象结构相同的本地记录类型:
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);
This SQL Fiddle demo编译并运行,使用固定数据类型而不是%TYPE
变量。
将集合作为OUT变量并直接使用它可能更简单,但它取决于使用它的其他位置。如果你需要两者,你可以有一个填充集合的过程,以及一个调用它的包装器过程并打开一个引用光标以给你灵活性。 (或者一个流水线函数,或任何适合你如何使用结果的函数)。
顺便说一句,不要抓住when others
例外;你重新提升它,这是一种东西,但是你失去了异常的实际位置,如果它破坏了它将使调试变得更加困难。只捕获您需要处理的特定异常。
答案 1 :(得分:0)
定义具有相同属性的本地类型t_ref_gen_record
将起作用,但需要将匿名块添加为另一个包中的过程。所以我所做的是在脚本中初始化相同的变量,如在类型中,并使用fetch将transfer_costs
的out参数的值输入到这些变量中。这工作得很好。我只使用三个变量的原因是因为在transfer_costs
过程中,类型被初始化,并且其中只有三个变量被赋予了值。我现在纠正了它。