2014-12-29 43 views
0

在包pkg_cost_api中定義了以下內容。在oracle中的匿名塊中引用通用遊標

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. 

可以請別人告訴我,究竟我做錯了這裏。

+1

您可以添加完整的錯誤堆棧,可能對查看異常是來自匿名塊還是來自程序內部有用,並且無論哪種方式確切地說是哪一行。 (我認爲這是'fetch into',但請確認。)在你的過程中查詢的數據類型是什麼,它填充了ref cursor?這聽起來像他們不匹配塊中的局部變量類型。 –

+0

錯誤報告: ORA-06504:PL/SQL:結果集變量或查詢的返回類型不匹配 ORA-06512:在行39 06504. 00000 - 「PL/SQL:結果集變量或查詢的返回類型不匹配」 *原因:在查詢號碼和/或列類型不匹配聲明的結果設置爲可變的 返回類型或聲明的類型兩個結果 設置變量的不匹配。 *操作:更改程序語句或聲明。驗證什麼查詢執行過程中的變量 實際上指的。 –

+0

@AlexPoole請發現上述錯誤堆棧。此外,我已經用附加信息更新了問題的描述。 –

回答

0

當查詢的對象類型爲8時,您試圖將您的遊標光標抓取到三列中。我不認爲有任何方式直接獲取到一個對象,但您可以定義具有相同結構作爲對象的本地記錄類型:

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異常;你正在重新提高它,這是某種東西,但是你正在失去異常的實際位置,如果中斷會使它更難以調試。只捕捉您需要處理的特定異常。

+0

感謝@alexpoole。限定具有相同屬性的本地類型是t_ref_gen_record將工作,但匿名塊需要被添加作爲另一個包的過程。所以我所做的就是我初始化相同的變量,如類型,在我的劇本和使用的取獲得transfer_costs的輸出參數的值代入這些變量。這工作得很好。我只用三個變量的原因是因爲在transfer_costs程序的類型被初始化,只有三個是變量給出的值。我現在糾正了它。再次感謝您的回覆。 –

0

定義一個具有相同屬性的本地類型t_ref_gen_record可以工作,但需要將該匿名塊添加爲另一個包中的過程。因此,我所做的是我在腳本中初始化了與該類型相同的變量,並使用獲取將out參數transfer_costs的值存入這些變量中。這工作得很好。我只使用三個變量的原因是因爲在transfer_costs過程中,類型被初始化,並且只有三個變量被賦值。我現在糾正了它。