带有游标的pl / sql varray

时间:2013-03-01 20:55:17

标签: database oracle plsql plsqldeveloper

有人能告诉我这段代码有什么问题。我的目标是编写一个传递员工姓名的程序,将员工表中的所有姓名和工资加载到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;

1 个答案:

答案 0 :(得分:9)

首先:PL / SQL集合不是基于0的。这将使下标超出限制误差,因为你的计数器盯着0。你也不需要这个解决方案的计数器。如果要继续使用它,请参阅第一个示例。但如果我是你,我会使用第二个例子。

其次,你在循环之前扩展了varray。这将使一个下标超出count错误,因为varray只被扩展为保持一行。您需要在循环的开头扩展它,以便在每次迭代时扩展varray。

但是,你不能PUT_LINE整个变种。您必须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,请使用下面的第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;

实际上你不需要计数器。如果您愿意放弃它,请使用varray的COUNT方法:

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;