0

我正在尝试实现一个游标,在解决了许多错误之后,我终于到达了它运行的地步,但它进入了无限循环......我将下面的表格图像作为图像。光标目标:计算保龄球平均值并存储在“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 中运行它。我寻求帮助以找出错误。提前致谢。

4

1 回答 1

3

在代码中添加空格可以让你更清楚地知道你在做什么:

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 语句将显着提高效率。

于 2013-10-13T17:45:57.607 回答