Я получил ошибку ORA-06531: ссылка на неинициализированную коллекцию - PullRequest
0 голосов
/ 25 сентября 2019

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

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

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

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

create type vrec_type is table of vrec;
/

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

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;
/

Ответы [ 2 ]

2 голосов
/ 25 сентября 2019

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

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

salary := vrec_type();
salary.extend;
0 голосов
/ 25 сентября 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;
...