2013-03-01 30 views
2

有人能告訴我這段代碼有什麼問題。我的目標是編寫一個傳遞員工姓名的程序,將員工表中的所有姓名和薪水加載到VARRAY中,然後在屏幕上打印姓名和薪水。pl/sql varray用光標

CREATE OR REPLACE PROCEDURE VARRAY_Q2 
(
    PNAME IN VARCHAR2 
, PSAL OUT NUMBER 
) AS 

--declare and create cursor 

CURSOR emp_cur IS 
SELECT ename,sal 
FROM EMP; 

    TYPE varray_emp IS VARRAY(14) OF emp_Cur%ROWTYPE; 

    --Creating new instance of varray 
    x_varray_emp varray_emp := varray_emp(); 
    v_counter NUMBER := 0; 

BEGIN 

    x_varray_emp.EXTEND; 

    FOR empRecs IN emp_Cur LOOP 

    --Insert data into the varray 
    x_varray_emp(v_counter) := empRecs; 

    dbms_output.put_line(v_counter); 

    v_counter := v_counter + 1; 
    END LOOP; 

    --Loop through the varray and print out all the elements 
    FOR i IN x_varray_emp.FIRST .. x_varray_emp.LAST 
    LOOP 
    dbms_output.put_line(x_varray_emp(i));  
    END LOOP; 

END; 
+0

1.爲什麼如果他們不使用任何參數傳遞到過程? 2.當你可以在遊標循環中完成你的操作時,爲什麼還要煩惱VARRAY? 3.如果你沒有看到輸出,你可能想'設置serveroutput'。 – Glenn 2013-03-01 21:56:41

+0

你有什麼錯誤? – Allan 2013-03-01 21:57:10

+0

@Glenn我認爲他正在學習如何做到這一點,並且在將這部分內容呈現出來之後將使用參數和varray。 – 2013-03-01 22:05:45

回答

9

第一:PL/SQL集合不是基於0的。這會使下標超出極限誤差,因爲您的計數器盯着0.您也不需要此解決方案的計數器。如果你想繼續使用它,請看第一個例子。但如果我是你,我會用第二個例子。

其次,你在循環之前擴展了varray,這將拋出一個超出count錯誤的下標,因爲varray只擴展爲保存一行。您需要在循環的開始處擴展它,以便在每次迭代時擴展varray。

提示,你不能PUT_LINE整個varray。您必須put_line varray中的元素。所以在這個例子中,而不是dbms_output.put_line(x_varray_emp(i))用這個代替:dbms_output.put_line(x_varray_emp(i).ename || ' makes $' || x_varray_emp(i).sal)

第四:如果你的emp表有超過14條記錄,你的VARRAY(14)會導致下標超出限制誤差。 varrays的最大大小設置爲他們(有界限制),在你的情況下是14.在這個例子中,我會使用一個規則的嵌套表(TYPE nested_emp IS TABLE OF emp_cur%ROWTYPE),以便不用擔心有界的限制(從技術上講,嵌套表具有最多2147483647又名PLS_INTEGER)。如果您願意在VA上使用NT,請改爲使用下面的第三種解決方案。

執行以下操作即可使用。

將您的v_counter NUMBER := 0更改爲v_counter NUMBER := 1;

變化即是在身體這一點:

BEGIN 
    FOR empRecs IN emp_Cur LOOP 
     x_varray_emp.EXTEND; 
     --Insert data into the varray 
     x_varray_emp(v_counter) := empRecs; 

     dbms_output.put_line(v_counter); 

     v_counter := v_counter + 1; 
    END LOOP; 
    --Loop through the varray and print out all the elements 
    FOR i IN x_varray_emp.FIRST .. x_varray_emp.LAST LOOP 
     dbms_output.put_line(x_varray_emp(i).ename || ' Makes $' || x_varray_emp(i).sal); 
    END LOOP; 
END; 

你並不需要一個計數器,其實。如果你願意放棄它,使用變長數組,而不是COUNT方法:

​​

我寧願你使用嵌套表對於這個問題在變長數組。如果你願意,這裏是解決方案:

DECLARE 

    CURSOR emp_cur IS SELECT ename,sal FROM EMP; 
    TYPE nestedtable_emp IS TABLE OF emp_cur%ROWTYPE; 

    x_nestedtable_emp nestedtable_emp := nestedtable_emp(); 
BEGIN 


    FOR empRecs IN emp_Cur LOOP 
     x_nestedtable_emp.EXTEND; 

     --Insert data into the varray 
     x_nestedtable_emp(x_nestedtable_emp.count) := empRecs; 

     dbms_output.put_line(x_nestedtable_emp.count); 


    END LOOP; 

    --Loop through the varray and print out all the elements 
    FOR i IN x_nestedtable_emp.FIRST .. x_nestedtable_emp.LAST LOOP 
     dbms_output.put_line(x_varray_emp(i).ename || ' Makes $' || x_varray_emp(i).sal); 
    END LOOP; 


END; 
+0

如果我們使用嵌套表BULK COLLECT將是一個更好的方法。但是這個任務不需要任何集合:一個簡單的FOR CURSOR循環就是所有需要的。這只是表明這種作業練習的無用性:他們教授語言的機制,但不知道如何正確使用它。因此,所有學生實際學習的是如何編寫不良的PL/SQL。 – APC 2013-03-02 08:02:49