Q:

How to correctly handle EOleException with massive UPDATE in for-loop?

Each worker thread of my app performs massive UPDATE operations on a remote SQL Server database. I use the for..do construction to iterate through the recordset which contains the input data for further updates:
try
   for i := 0 to RS.RecordCount-1 do
   begin
      // omitting the quotes for brevity
      CN.Execute('my_stored_proc ' + RS.Fields['Dummy'].Value);
      RS.MoveNext;
   end;
 except
   on E: Exception do
   begin
     // At the moment here is a simple notice of the exception thrown
     ShowMessage(E.ClassName + ': ' + E.Message);
   end;

I noticed that EOleException is raised quite often with the E.Message = "Query timeout expired". That obviously means that the thread waits for SQL Server to respond and then aborts the current request. Then (according to the logs) the thread submits new i value just ignoring the previous one. So if the EOleException thrown on i = 613 the handler merely moves to i = 614 and keeps on working leaving 613 a virgin.
My question is:
What is the correct way of handling such kind of exceptions, making sure all records would be processed anyway, even if they caused exceptions a few slices back?
Should I just go for while..do / repeat..until constructions where I can simply Dec(i) in the handler or are there more eclectic techniques?

A:

The code you have shown WILL NOT process the next record if Execute() raises an exception.  Your entire loop is exited instead.  To do what you are asking for, you need to handle the exception inside of the loop, not outside.
You also should not be using the RecordCount property. Use the Eof property instead.
Try this:
try
  while not RS.Eof do
  begin
    try
      // omitting the quotes for brevity
      CN.Execute('my_stored_proc ' + RS.Fields['Dummy'].Value);
    except
      on E: EOleException do
      begin
        if E.Message = 'Query timeout expired' then
          Continue;
        raise;
      end;
    end;
    RS.MoveNext;
  end;
except
  on E: Exception do
  begin
    // At the moment here is a simple notice of the exception thrown
    ShowMessage(E.ClassName + ': ' + E.Message);
  end;
end;

