16 April 2011

Yes, cursor FOR loops can be infinite loops! (2205)

In the 15 April quiz on infinite loops scored the following as incorrect (not an infinite loop):
BEGIN
   sys.DBMS_OUTPUT.disable ();

   FOR rec IN (SELECT * FROM all_source)
   LOOP
      sys.DBMS_OUTPUT.put_line ('See you later!');
   END LOOP;
END;
/
and provided the following explanation: "A cursor FOR loop will never be an infinite loop, because a query can never return an infinite number of rows."

Ah, naive Steven! Ah, Steven of the limited understanding of SQL and all of its "tricks"!

Several players wrote to say that while the choice correctly identifies a query that will always return a finite number of rows, it is, in fact, possible to craft a query that returns an unlimited number of rows. They offered these examples:
BEGIN
   FOR c IN (    SELECT dummy
                   FROM DUAL
             CONNECT BY LEVEL > 0)
   LOOP
      DBMS_LOCK (sleep (1));
   END LOOP;
END;
/

BEGIN
   FOR c IN (SELECT *
               FROM (    SELECT LEVEL
                           FROM DUAL
                     CONNECT BY LEVEL < LEVEL + 1))
   LOOP
      DBMS_LOCK (sleep (1));
   END LOOP;
END;
/
Thanks for bringing this to my attention. I will change the answer text to reflect this "nuance" of SQL.

2 comments:

  1. SQL "tricks" aren't the only way to create cursors that return an infinite number of rows; referencing a pipelined table function that never terminates could also produce this undesirable result.

    ReplyDelete
  2. Just curious:

    The following line of both the examples provided in this post is invalid right?

    DBMS_LOCK (sleep (1));

    Did they mean

    DBMS_LOCK.sleep (1);
    ?

    Or is there a new feature of calling packaged procs enclosed in () instead of . ?

    ReplyDelete