Во-первых: PL/SQL Коллекции не основаны на 0. Это вызовет ошибку индексации из-за пределов, потому что ваш счетчик смотрел на 0. Вам также не нужен счетчик для этого решения. Если вы хотите продолжить использовать его, см. Первый пример. Но если бы я был вами, я бы использовал второй пример.
Во-вторых, вы расширили varray перед циклом. Это приведет к выкидыванию индекса за пределы ошибки подсчета, потому что varray был расширен только для того, чтобы удерживать одну строку. Вам нужно расширить его в начале цикла, чтобы на каждой итерации расширялся.
Thid, вы не можете 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). Если вы хотите использовать NT над VA, используйте вместо этого третье решение.
Сделайте следующее, и оно будет работать.
изменить 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
метод 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;
1. Почему вы передаете какие-либо параметры в процедуру, если они не используются? 2. Зачем беспокоиться о VARRAY, когда вы можете сделать свою операцию прямо в цикле курсора? 3. Если вы не видите вывод, вы, вероятно, хотите «установить serveroutput on». – Glenn
Какая ошибка вы получаете? – Allan
@Glenn Я думаю, он учится, как это сделать, и будет использовать параметры и varray после того, как он выберет эту часть. –