我看到了其他类似的问题,但是我无法理解代码中的问题。以下是过程定义
Proc.sql
set serveroutput on
create or replace type myarray is varray(1000) of number;
/
create or replace procedure Bill(cid in number , bill out number) is
md myarray;
q myarray;
pr myarray;
rs myarray;
begin
bill:=0;
select model,quantity BULK COLLECT into md,q from transactions where customer=cid;
for i in 1..md.COUNT loop
select price BULK COLLECT into pr from computers where model_no=md(i);
END LOOP;
for i in 1..md.COUNT loop
rs(i):=q(i)*pr(i);
end loop;
for i in 1..md.COUNT loop
bill:=bill+rs(i);
end loop;
end;
/
show errors;
这是我用于调用该过程的文件
CallProc.sql
set serveroutput on
declare
bll number(2):=0;
begin
Bill(1,bll);
DBMS_OUTPUT.PUT_LINE('T = '|| bll);
end;
/
答案 0 :(得分:1)
如果将数组初始化为空集合:
declare
...
rs myarray := myarray();
begin
然后,您必须increase its capacity,因为要遍历循环:
for i in 1..md.COUNT loop
rs.extend;
rs(i):=q(i)*pr(i);
end loop;
或一次性执行(应该更有效):
rs.extend(md.COUNT);
for i in 1..md.COUNT loop
rs(i):=q(i)*pr(i);
end loop;
在扩展空集合之前,您仍然必须初始化它。
您还有其他问题。您正在做
rs(i):=q(i)*pr(i);
,但是rs
和pr
集合是完全独立的,因此它们的索引没有关系。我认为您每次尝试在此循环中将记录添加到pr
:
for i in 1..md.COUNT loop
select price BULK COLLECT into pr from computers where model_no=md(i);
END LOOP;
但是您实际上是在用单个值而不是附加值替换整个集合的内容。并且在该循环结束时,您只会获得md
集合中最后一行的价格。对于该集合有效的唯一i
值为1,因为只有pr(1)
存在(假设model_no
是唯一的);除非客户只进行了一笔交易,但最后一个模型(i = 1)除外,否则交易价格不正确。
您可以在循环内获取相关价格,而无需为此付费:
create or replace procedure Bill(cid in number , bill out number) is
md myarray;
q myarray;
pr number; -- scalar variable
rs myarray := myarray();
begin
select model, quantity bulk collect into md, q from transactions where customer=cid;
rs.extend(md.COUNT);
for i in 1..md.COUNT loop
select price into pr from computers where model_no=md(i); -- not bulk collect
rs(i):=q(i)*pr; -- pr no longer indexed
end loop;
bill:=0;
for i in 1..md.COUNT loop
bill:=bill+rs(i);
end loop;
end;
/
通过联接表格并将单个批量收集添加到所有三个收集中,使价格与其余数据保持一致会更有效:
create or replace procedure Bill(cid in number , bill out number) is
md myarray;
q myarray;
pr myarray;
rs myarray := myarray();
begin
select t.model, t.quantity, c.price
bulk collect into md, q, pr
from transactions t
join computers c on c.model_no = t.model
where t.customer = cid;
rs.extend(md.COUNT);
for i in 1..md.COUNT loop
rs(i):=q(i)*pr(i);
end loop;
bill:=0;
for i in 1..md.COUNT loop
bill:=bill+rs(i);
end loop;
end;
/
但是,您可以通过一次循环执行两种计算来进一步简化:
bill:=0;
rs.extend(md.COUNT);
for i in 1..md.COUNT loop
rs(i):=q(i)*pr(i);
bill:=bill+rs(i);
end loop;
从中您可以看到根本不需要rs
,您可以直接计算账单更改:
create or replace procedure Bill(cid in number , bill out number) is
md myarray;
q myarray;
pr myarray;
begin
select t.model, t.quantity, c.price
bulk collect into md, q, pr
from transactions t
join computers c on c.model_no = t.model
where t.customer = cid;
bill:=0;
for i in 1..md.COUNT loop
bill := bill + q(i)*pr(i);
end loop;
end;
/
但是您根本不需要循环或集合:
create or replace procedure Bill(cid in number , bill out number) is
begin
select sum(t.quantity * c.price)
into bill
from transactions t
join computers c on c.model_no = t.model
where t.customer = cid;
end;
/
显然,您可以将查询作为纯SQL运行,而无需涉及PL / SQL或过程。
取决于您的作业告诉您使用什么...