在正常的 oracle 函数中:ORA-06531:引用未初始化的集合

in normal oracle function : ORA-06531: Reference to uninitialized collection

我的函数执行完美,但在声明时显示错误。代码是:

set serveroutput on

create or replace type myarray is varray(10000) of number;

create or replace function T_Bill (cus_id in integer) return number as
    t_cost number:=0;
    n integer;   
    bk myarray;
    pr myarray;
    q myarray;   
begin
    select count(book_id) into n from issue where cust_id=cus_id;
    select book_id,quantity BULK COLLECT into bk,q from issue where cust_id=cus_id;
    for i in 1..n
    loop
        select price into pr(i) from book where ISBN=bk(i);
        DBMS_OUTPUT.PUT_LINE(bk(i)||' '||q(i));
        t_cost:=pr(i);
    end loop;

    return t_cost;
end;
/

我是这样声明的:

declare 
 x integer:=1;
 begin
 DBMS_OUTPUT.PUT_LINE(T_Bill(x));
 end;
 /

错误是:

ORA-06531: Reference to uninitialized collection
ORA-06512: at "R1507090.T_BILL", line 12
ORA-06512: at line 4

提前致谢。

您在尚未初始化集合时尝试设置 pr(i)。此外,您正在覆盖 t_cost 循环的每次迭代。

create or replace function T_Bill (
  cus_id in integer
)
  return number
as
  t_cost number:=0;
  bk myarray;
  pr myarray;
  q  myarray;   
begin
  select book_id,quantity
  BULK COLLECT into bk,q
  from issue
  where cust_id=cus_id;

  pr := myarray();               -- Initialise the collection
  pr.EXTEND( bk.COUNT );         -- Set the size of the collection

  FOR i IN 1..bk.COUNT LOOP
    select price into pr(i) from book where ISBN=bk(i);
    DBMS_OUTPUT.PUT_LINE(bk(i)||' '||q(i));
    t_cost:= t_cost + pr(i);
  END LOOP;

  return t_cost;
end;
/

然而,最简单的解决方案是使用连接并同时填充所有集合(假设在 ISBN 主键上存在从问题到书籍的多对一关系):

create function T_Bill (
  cus_id in ISSUE.CUST_ID%TYPE
)
  return number
as
    t_cost number :=0;
    bk myarray;
    pr myarray;
    q  myarray;   
begin
  select i.book_id,
         i.quantity,
         b.price
  BULK COLLECT into
         bk,
         q,
         pr
  from   issue i
         LEFT OUTER JOIN book b     -- INNER JOIN?
         ON ( i.book_id = b.ISBN )
  where  i.cust_id = cus_id;

  FOR i IN 1..n LOOP
    DBMS_OUTPUT.PUT_LINE(bk(i)||' '||q(i));
    t_cost:= t_cost + pr(i);
  END LOOP;

  return t_cost;
end;
/