Я получил ошибку ORA-06531: ссылка на неинициализированную коллекцию

Я создаю процедуру для отображения n-го числа максимальной и минимальной заработной платы для сотрудника. Если я дам 5 в качестве входных данных, запрос даст мне максимальную и минимальную зарплату 5 для сотрудника.

Для приведенного выше сценария я создал объект с двумя столбцами, как показано ниже.

create type vrec as object(
empno number,
sal number
);
/

Затем я создал вложенную таблицу с помощью типа объекта, чтобы я мог использовать вложенную таблицу в качестве выходного параметра для возврата всех строк за один раз.

create type vrec_type is table of vrec;
/

После создания типа данных я создаю процедуру, как показано ниже.

create or replace procedure pro_first_last1(input in number,salary out vrec_type)
as
n number:=0;
begin
salary.extend;
select vrec(empno,sal) into salary(n) from (
select * from (select empno,sal,rank() over(order by sal asc) min_sal from emp5) where min_sal <= input
union all
select * from (select empno,sal,rank() over(order by sal asc) max_sal from emp5) where max_sal <= input);
n:=n+1;
for i in 1..salary.count
loop
dbms_output.put_line(salary(i).empno||'    '||salary(i).sal);
end loop;
end;
/

Также процедура успешно скомпилирована.

Но когда я запустил приведенный ниже блок, чтобы получить вывод, я получил ошибку «Ссылка на неинициализированный сборник».

declare
input number:=5;
salary vrec_type;
begin
pro_first_last1(input,salary);
end;
/

person Raja sekar    schedule 25.09.2019    source источник


Ответы (2)


В вашей процедуре переменная salary представляет собой переменную nested table, которая требуется для инициализации до того, как вы сможете вызвать salary.extend;

Вы можете инициализировать его пустым конструктором следующим образом:

salary := vrec_type();
salary.extend;
person kfinity    schedule 25.09.2019
comment
Если я внес указанные вами изменения и попытаюсь запустить приведенный ниже блок, я получаю, что точная выборка возвращает больше, чем запрошенное количество строк, ошибка. объявить входной номер:=5; зарплата vrec_type; начать pro_first_last1 (вход, зарплата); конец; / - person Raja sekar; 25.09.2019

Вам не нужно запускать цикл. Более быстрая и короткая версия будет такой:

select vrec(empno,sal) 
BULK COLLECT into salary 
from 
   (select * from (select empno,sal,rank() over(order by sal asc) min_sal from emp5) 
    where min_sal <= input
    union all
    select * from (select empno,sal,rank() over(order by sal asc) max_sal from emp5)
    where max_sal <= input);

Кстати, ваш запрос не имеет особого смысла. Выражение rank() over(order by sal asc) используется дважды. Один раз вы используете его как min_sal, один раз как max_sal - для одного и того же выражения?

Если вы используете Oracle 12.2 или новее, вы также можете использовать пункт ограничения строк.

with minSal as 
   (select empno,sal
    from emp5
    order by sal ASC
    FETCH FIRST input ROWS WITH TIES),
maxSal as
    (select empno,sal
    from emp5
    order by sal DESC
    FETCH FIRST input ROWS WITH TIES),
allSal as
    (select * from minSal 
    UNION ALL
    select * from minSal) 
select vrec(empno,sal) 
BULK COLLECT into salary 
from allSal;
person Wernfried Domscheit    schedule 25.09.2019
comment
Я могу сделать это с массовым сбором, но я не могу обойтись без массового сбора. Без использования массового сбора я не могу успешно получить желаемые результаты - person Raja sekar; 25.09.2019