繁体   English   中英

在oracle中的匿名块中引用通用游标

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM