First: PL/SQL Collections are not 0 based. That will throw a subscript out of limit error because your counter stared at 0. You also do not need a counter for this solution. If you want to continue to use it, see the first example. But if I were you I would use the second example.
Second, you extended the varray before the loop.That will throw a subscript beyond count error because the varray has only been extended to hold one row. You need to extend it at the beginning of the loop so that upon each iteration the varray is extended.
Thid, you cannot PUT_LINE
a whole varray. You have to put_line
the elements in the varray. So in this example, rather than dbms_output.put_line(x_varray_emp(i))
use this instead: dbms_output.put_line(x_varray_emp(i).ename || ' makes $' || x_varray_emp(i).sal)
Fourth: if your emp table has more than 14 records in it, your VARRAY(14)
will cause a subscript outside of limit error. varrays have a max size set to them (bounded limit), which in your case is 14. In this example, I would have used a regular nested table (TYPE nested_emp IS TABLE OF emp_cur%ROWTYPE
) so as to not worry about bounded limits (technically, a nested table has a maximum of 2147483647 aka PLS_INTEGER). If you are willing to use a NT over a VA, use the 3rd solution below instead.
Do the following and it will work.
change your v_counter NUMBER := 0
to v_counter NUMBER := 1
;
Change that which is in the BODY to this:
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;
You don't need a counter, actually. If you are willing to abandon it, use the COUNT
method of the varray instead:
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;
I would prefer that you use a nested table for this problem over a varray. IF you are willing, here is the solution:
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;