【问题标题】:I got the error ORA-06531: Reference to uninitialized collection我收到错误 ORA-06531: Reference to uninitialized collection
【发布时间】:2020-01-25 20:40:58
【问题描述】:

我正在创建一个程序来显示员工的最高和最低工资的 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;
/

【问题讨论】:

    标签: oracle object stored-procedures plsql nested-table


    【解决方案1】:

    您不必运行循环。一个更快更短的版本是这样的:

    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;
    

    【讨论】:

    • 我可以通过批量收集来做到这一点,但如果没有批量收集,我就无法做到。如果不使用批量收集,我无法成功获得所需的结果
    【解决方案2】:

    在你的过程中,salary 变量是一个nested table,在你可以调用salary.extend; 之前needs to be initialized

    你可以像这样用一个空的构造函数来初始化它:

    salary := vrec_type();
    salary.extend;
    

    【讨论】:

    • 如果我进行了您指定的更改并尝试运行以下块,我会得到精确的提取返回超过请求的行数错误。声明输入数:=5;工资 vrec_type;开始 pro_first_last1(输入,薪水);结尾; /
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多