Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question.

Asked: March 29, 2001 - 1:46 pm UTC

Last updated: April 02, 2001 - 8:23 pm UTC

Version: 8.1.6

Viewed 1000+ times

You Asked

Hi, TOm,

Here is a example ( Note its not a puzzle, it's just something one of our customers wrote which landed up in infinite loop in SQL server, this could happen with Oracle too..)

This example might not be syntactically correct.. but shows what they did..this is a part of a stored procedure (Oracle version 8.0.6 on NT)

DECLARE CURSOR Temp_work_cursor
IS
SELECT Temp_work_ID, Temp_work_level
FROM branchtemp
where Temp_work_level > 5
and temp_date between x and y;

Begin
OPEN Temp_work_cursor ;
Loop
FETCH Temp_work_cursor
INTO inOld_ID, inLevel;
EXIT WHEN Temp_work_cursor%NOTFOUND;

For date between x and y
begin
insert into branchtemp(Temp_work_ID, temp_work_level, temp_date)
values(temP_work_id_seq.nextval, 5, x);
x= x+1
end for loop;

End loop;
CLOSE Temp_work_cursor;
End ;

--------------------------------------------------
What this is doing is selecting a records from a table by opening a cursor for perticular date range and then inserting records to the same table for that date range.


Now my question is if the cursor fetches all the rows which satisfies the where clause at 1st before opening it, it will not go in infinite loop right because it will have fixed number of rows before processing ?
But if the cursor is fetching records from a table after each loop

OPEN Temp_work_cursor ;
Loop
...
...
...
End loop;

In this case it will go in infinite loop right , because the next time it fetches records from the table it will have more records matching the condition and so on...


Note: this is cursor technically might not make sense because I took out other logic to make it simple.


So how doses cursor work ? Does it keep records in memory the 1st time you declare and those are the only rows it will process or does it selects from the table after each loop ?


and Tom said...

I remember doing that to myself in Sybase once upon a time ago myself. It was the infinite table!

I used isql to generate updates and piped that into isql. something like:

for x in ( select * from t )
loop
print 'update t set .... where ....'
print 'go'
end

and piped the updates into isql. The first row would be updated -- but that was really a DELETE and an INSERT. the insert (it was a non-clustered table mind you) went the last page of course. By the time we got to the end of the table -- it read the first row we updated AGAIN. After it had updated 25,000 records (out of 5,000 rows in the table) I knew something was up.


That is PHYSICALLY impossible in Oracle. It is only too easy in Sybase and SQLServer.

We use a multi-versioning scheme that GUARANTEES a consistent result set. See
</code> http://docs.oracle.com/cd/A81042_01/DOC/server.816/a76965/c23cnsis.htm#17882 <code>

Basically, the results of your query are pre-ordained at the point in time you open the query (before you fetch the first row). We do not make a copy of this in memory or get all of the rows or anything like that, rather we use the rollback segments to provide consistent reads.

Read that section in the server concepts and feel free to followup on this. One of my favorite topics actually. It is really something you need to understand. It is how we provide non-blocking reads as well.


Rating

  (2 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Reader, March 29, 2001 - 3:30 pm UTC


A reader, April 02, 2001 - 8:23 pm UTC


More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library