在代码中添加空格可以让你更清楚地知道你在做什么:
declare
cursor bowl_avg is
select sid, matches, bowling_avg, wickets
from bowling_stats;
nsid bowling_stats.sid%type;
nmatches bowling_stats.matches%type;
nbowling_avg bowling_stats.bowling_avg%type;
nwickets bowling_stats.wickets%type;
begin
-- 1. Open Cursor
open bowl_avg;
-- 2. Check if Cursor is open
if bowl_avg%isopen then
-- 3. Loop
loop
-- 4. Get record
fetch bowl_avg into nsid, nmatches, nbowling_avg, nwickets;
-- 5. Exit if no records left
exit when bowl_avg%notfound;
-- 6. If there is a record
if bowl_avg%found then
-- 7. Loop
loop
update bowling_stats
set bowling_avg = nwickets / nmatches
where sid = nsid;
-- 8. Exit if there is no record.
exit when bowl_avg%notfound;
end loop;
end if;
end loop;
else
dbms_output.put_line('unable to open cursor');
end if;
close bowl_avg;
end;
/
里面有很多矛盾。
- 在 1 和 2 中,您正在打开一个游标,然后检查是否有一个打开的游标。如果光标未打开,则会引发错误,因此您可以忽略此步骤。
- 如果无法获取新记录,则在 5 和 6 中退出,然后检查是否有记录。这是一个矛盾,因此第 6 阶段将(几乎)总是评估为真。
- 在 7 和 8 中你循环,当你没有记录时退出。正如你刚刚检查过(两次)你确实有一个记录,你永远不会退出这个循环。
如果您坚持使用游标执行此操作,那么您可以删除大部分代码,它应该可以正常工作:
declare
cursor bowl_avg is
select sid, matches, bowling_avg, wickets
from bowling_stats;
nsid bowling_stats.sid%type;
nmatches bowling_stats.matches%type;
nbowling_avg bowling_stats.bowling_avg%type;
nwickets bowling_stats.wickets%type;
begin
-- 1. Open Cursor
open bowl_avg;
-- 2. Loop
loop
-- 3. Get record
fetch bowl_avg into nsid, nmatches, nbowling_avg, nwickets;
-- 4. Exit loop if there is no record.
exit when bowl_avg%notfound;
-- 5. Perform UPDATE statement.
update bowling_stats
set bowling_avg = nwickets / nmatches
where sid = nsid;
end loop;
close bowl_avg;
end;
/
与往常一样,不使用循环、游标或 PL/SQL 的单个 UPDATE 语句将显着提高效率。