2

誰かがこのコードの何が問題なのか教えてもらえますか?私の目的は、従業員の名前が渡され、すべての名前と給与が従業員テーブルから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;
4

1 に答える 1

9

最初: PL/SQL コレクションは 0 ベースではありません。カウンターが0を見つめているため、添字が制限外エラーをスローします。また、このソリューションにはカウンターは必要ありません。引き続き使用する場合は、最初の例を参照してください。しかし、私があなたなら、2 番目の例を使用します。

第 2 に、ループの前に varray を拡張しました。varray は 1 行を保持するように拡張されているだけなので、subscript beyond count エラーがスローされます。反復ごとに varray が拡張されるように、ループの開始時に拡張する必要があります。

PUT_LINEつまり、 VARRAY 全体を使用することはできません。put_linevarray の要素が必要です。したがって、この例では、dbms_output.put_line(x_varray_emp(i))代わりにこれを使用するのではなく:dbms_output.put_line(x_varray_emp(i).ename || ' makes $' || x_varray_emp(i).sal)

4 番目: emp テーブルに 14 を超えるレコードが含まれている場合VARRAY(14)、添え字が制限外エラーになります。varray には最大サイズが設定されています (境界制限)。あなたの場合は 14 です。この例では、TYPE nested_emp IS TABLE OF emp_cur%ROWTYPE境界制限を気にしないように、通常のネストされたテーブル (最大 2147483647 別名 PLS_INTEGER)。VA ではなく NT を使用する場合は、代わりに以下の 3 番目のソリューションを使用してください。

以下を実行すると、動作します。

に変更v_counter NUMBER := 0しますv_counter NUMBER := 1

BODY にあるものを次のように変更します。

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、代わりに varray のメソッドを使用してください。

BEGIN


    FOR empRecs IN emp_Cur LOOP
        x_varray_emp.EXTEND;

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

        dbms_output.put_line(x_varray_emp.count);


    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;

この問題には、VARRAY よりもネストされたテーブルを使用することをお勧めします。よろしければ、解決策は次のとおりです。

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;
于 2013-03-01T21:57:59.393 に答える