Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When you do not need to close a cursor in oracle?

I am working in Oracle 10.2 with TOAD.

I have a script similar to this:

DECLARE

my_query VARCHAR2(500) := 'select C1, C2, C3 FROM  MYSCHEMA.MYTABLE';

    TYPE my_record_type IS RECORD
    (
           C1 MYTABLE.C1%TYPE,
           C2 MYTABLE.C2%TYPE,           
           C3 MYTABLE.C3%TYPE
    );

    TYPE my_table_type IS TABLE OF my_record_type;
    my_records my_table_type;

     my_cursor SYS_REFCURSOR;
BEGIN
     OPEN my_cursor FOR my_records;
        FETCH my_cursor
        BULK COLLECT INTO my_records
        LIMIT 1000;                           

        FOR indx IN 1 .. my_records.COUNT
        LOOP

            /* SOME CODE HERE*/
            IF /* CONDITION */ THEN
                EXIT;
            END IF; 
        END LOOP;
    CLOSE my_cursor;
END;

I have read that if you CLOSE a cursor that is already closed, oracle will raise the INVALID_CURSOR exception.

I have also read that when you use a CURSOR in a FOR LOOP oracle closes the cursor explicitly when the LOOP ends. So in theory I don't need to CLOSE the cursor as I am, and I should get an exception, which I am not.

Now I need to add a condition inside the LOOP that will cause it to EXIT the LOOP. I read that oracle implicitly closes CURSORS when you use EXIT inside a FOR LOOP or when an EXCEPTION is thrown.

So should I close the CURSOR explicitly? If I do so, and the CURSOR gets closed because I called EXIT, should it throw an Exception?

If I remove the explicit call that closes the cursor, will I get memory leaks?

What is the correct way to use the CURSOR in this case?

like image 585
Dzyann Avatar asked Oct 20 '25 04:10

Dzyann


2 Answers

It seems that you're confusing cursors in for loops with cursor for loops. The former is what you illustrated. The latter looks like this:

DECLARE    
   cursor my_cursor is select C1, C2, C3 FROM  MYSCHEMA.MYTABLE;
BEGIN         
        FOR my_record in my_cursor LOOP    
            /* SOME CODE HERE*/
            IF /* CONDITION */ THEN
                EXIT;
            END IF; 
        END LOOP;
    CLOSE my_cursor;
END;

In this case, the close statement will throw an error because the cursor was implicitly opened by the for statement and implicitly closed when the loop concluded.

To summarize, if you have an open statement, you should also have a close statement. If you implicitly open a cursor, you can trust that it will be implicitly closed.

like image 64
Allan Avatar answered Oct 22 '25 06:10

Allan


There's a simple rule - if you have to code an OPEN statement to open the cursor, you must code a matching CLOSE statement to close the cursor.

Thus if you have

DECLARE
  CURSOR some_cursor IS SELECT * FROM SOME_TABLE;
  some_table_row  SOME_TABLE%ROWTYPE;
BEGIN
  OPEN some_cursor;

  LOOP
    FETCH some_cursor INTO some_table_row;
    EXIT WHEN some_cursor%NOTFOUND;  -- this exit **WILL NOT** close some_cursor
  END LOOP;

then at some point later in your code you must have

  CLOSE some_cursor;
END;

If you use a cursor FOR-loop to open the cursor, e.g.

BEGIN
  FOR aRow IN some_cursor LOOP
    -- whatever

    IF aRow.SOME_THING = 'xyz' THEN
      EXIT;  -- this EXIT **will** close the cursor
    END IF;
  END LOOP;

or in the case where you don't even have an explicit cursor declaration:

FOR aRow IN (SELECT * FROM SOME_TABLE) LOOP
  -- blah, blah

  IF aRow.YADA_YADA = 'BADA BOOM!' THEN
    EXIT;  -- this EXIT **will** close the cursor
  END IF;
END LOOP;

then you don't need or want to write a CLOSE statement.

Share and enjoy.

like image 34


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!