0

I'm trying to implement a cursor, & after solving many errors I've finally come to a point where it runs, but it goes into infinite loop... I've put the image of table below as image. Aim of cursor: to calculate bowling average & store in 'bowling_avg' column. here's the cursor code :

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;

enter image description here

I'm running this in oracle database 10g. I ask for assistance in finding the error. Thanks in advance.

7
  • 1
    Why all your code in capital letters? Commented Oct 13, 2013 at 17:28
  • my professor believes capital letters make it easier to find errors... Commented Oct 13, 2013 at 17:32
  • :-), that's both the best and worst answer I've heard to that question! You have far too many loops here, that's why. Remove all bar the outer one. Commented Oct 13, 2013 at 17:35
  • 2
    There are many coding styles for many programming languages and not even one of them says that all your code should be in capital letter. Commented Oct 13, 2013 at 17:37
  • @Ben,yes,I agree with that... Commented Oct 13, 2013 at 17:41

1 Answer 1

3

Adding whitespace to your code makes it clearer what you're doing:

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;
/

There are a number of contradictions in there.

  • In 1 and 2 you're opening a cursor and then checking if there is an open cursor. A error will be raised if the cursor didn't open so you can ignore this step.
  • In 5 and 6 you exit if you can't fetch a new record then check if you have a record. This is a contradiction so stage 6 will (almost) always evaluate to true.
  • in 7 and 8 you loop, exiting when you don't have a record. As you've just checked (twice) that you do in fact have a record you'll never exit this loop.

If you insist on doing this with cursors then you can remove most of your code and it should work fine:

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;
/

As always a single UPDATE statement without using loops, cursors or PL/SQL will be significantly more effective.

Sign up to request clarification or add additional context in comments.

4 Comments

Yes ofcourse a single update will suffice, but I've to do this as a project work, & its mandatory to use cursors. I tried running the optimized code,however there's still an infinite loop. I suspect I'm missing out something very important here. Any guesses ?? Also, I really appreciate your help.I knew my code wasnt that clean, but thanks to you,I know that it was much worse than what I thought...
I doubt you're getting an infinite loop @Sumedh. As your cursor is selecting every row in the table this may take some time, especially if you don't have an index on sid.
Here it is working in a SQL Fiddle @Sumedh.
Ok, now its working fine....dont know what happened back then. Thanks for all this help !!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.