SQL 中的光标错误
Posted
技术标签:
【中文标题】SQL 中的光标错误【英文标题】:Cursor error in SQL 【发布时间】:2013-10-13 17:27:19 【问题描述】:我正在尝试实现一个游标,在解决了许多错误之后,我终于到达了它运行的地步,但它进入了无限循环...... 我把表格的图像放在下面作为图像。 光标目标:计算保龄球平均值并存储在“bowling_avg”列中。 这是光标代码:
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
OPEN BOWL_AVG;
IF BOWL_AVG%ISOPEN THEN
LOOP
FETCH BOWL_AVG INTO NSID,NMATCHES,NBOWLING_AVG,NWICKETS;
EXIT WHEN BOWL_AVG%NOTFOUND;
IF BOWL_AVG%FOUND THEN
LOOP
UPDATE BOWLING_STATS SET BOWLING_AVG=NWICKETS/NMATCHES WHERE SID=NSID ;
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;
我在 oracle 数据库 10g 中运行它。 我寻求帮助以找出错误。 提前致谢。
【问题讨论】:
为什么你的代码都是大写的? 我的教授认为大写字母更容易发现错误... :-),这是我听到的关于这个问题的最好和最差的答案!你这里有太多的循环,这就是原因。删除所有栏外的。 许多编程语言有多种编码风格,甚至没有一种说你所有的代码都应该大写。 @Ben,是的,我同意... 【参考方案1】:在你的代码中添加空格可以让你更清楚你在做什么:
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 阶段将 (almost) 始终评估为真。 在 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 语句将显着提高效率。
【讨论】:
是的,当然,一次更新就足够了,但我必须将此作为项目工作,并且必须使用游标。我尝试运行优化的代码,但是仍然存在无限循环。我怀疑我在这里错过了一些非常重要的东西。有什么猜测吗??另外,我真的很感谢你的帮助。我知道我的代码不是那么干净,但是感谢你,我知道它比我想象的要糟糕得多...... 我怀疑你得到了一个无限循环@Sumedh。当您的光标选择表中的每一行时,这可能需要一些时间,尤其是如果您在sid
上没有索引。
这里是working in a SQL Fiddle@Sumedh。
好的,现在它工作正常....不知道当时发生了什么。感谢所有这些帮助!以上是关于SQL 中的光标错误的主要内容,如果未能解决你的问题,请参考以下文章