Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 General SQL Server Forums
 New to SQL Server Programming
 Cursor Continue On Failure

Author  Topic 

GhantaBro
Posting Yak Master

215 Posts

Posted - 2009-07-10 : 00:45:38
Hey Guys,
I need some suggestion on this. I need to use files, stage them and create few reports. I have a logging table that has flags and a place holder to enter reasons for failures. What I need to do is periodically, I need to use that logging table and process the files that are not processed.... I am using a cursor to go through the file one by one... if say the processing fails on the 3rd file, I want to update the logging table with failure reasons and then continue on with the 4th file... Guys what is the best way to handle this scenario... any suggestion is appreciated. Do you think TRY Catch Error in Sql 2005 is helpful?

Thanks

GhantaBro
Posting Yak Master

215 Posts

Posted - 2009-07-10 : 00:52:26
I think I got it... I can use this approach..

When you do iterative processing, there are cases when you do not want to exit the procedure on first error. You go through a set of rows that are handled independently, and if an operation fails for one row, you may still want to try to process remaining rows, possibly setting an error flag for the failed row. Here is an outline of such a procedure may look like:

CREATE PROCEDURE error_demo_cursor AS

DECLARE @err int,
...
IF @@trancount > 0
BEGIN
RAISERROR ('This procedure must not be called with a transaction in progress', 16, 1)
RETURN 50000
END

DECLARE some_cur CURSOR FOR
SELECT id, col1, col2, ...
FROM tbl
WHERE status = 'New'
...
SELECT @err = @@error IF @err <> 0 BEGIN DEALLOCATE some_cur RETURN @err END

OPEN some_cur
SELECT @err = @@error IF @err <> 0 BEGIN DEALLOCATE some_cur RETURN @err END

WHILE 1 = 1
BEGIN
FETCH some_cur INTO @id, @par1, @par2, ...
SELECT @err = @@error
IF @err <> 0 OR @@fetch_status <> 0
BREAK

BEGIN TRANSACTION

EXEC @err = some_sp @par1, ...
SELECT @err = coalesce(nullif(@err, 0), @@error) IF @err <> 0 GOTO Fail

INSERT other_tbl (...)
SELECT @err = @@error IF @err <> 0 GOTO Fail

UPDATE tbl
SET status = 'OK'
WHERE id = @id
SELECT @err = @@error IF @err <> 0 GOTO Fail

COMMIT TRANSACTION
SELECT @err = @@error IF @err <> 0 BREAK

-- Handle next guy
CONTINUE

Fail:
ROLLBACK TRANSACTION
UPDATE tbl
SET status = 'Error'
WHERE id = @id
-- No error-checking here.
END

DEALLOCATE some_cur

RETURN @err
Here, if we get an error while we are handling the row, we don't want to exit the procedure, but only set an error status for this row and then move on to the next. The particular UPDATE statement where we set the status to 'Error' has no error checking, because – well, there is not really any action we can take if this UPDATE fails. If we for some reason cannot set the status, this is not reason to abort the procedure. As you see, there is a comment that explicitly says that there is no error checking, so that anyone who reviews the code can see that the omission of error checking is intentional.

If you look closer, you see that in some cases we abort the procedure in case of an error even within the loop. We do so for FETCH, because the most likely error with a FETCH statement is a mismatch between the variables and the column list in the cursor. In this case, all executions of the FETCH statement will fail, so there is no reason to hang around. A similar reasoning applies when it comes to COMMIT TRANSACTION. Errors with COMMIT are so unexpected, that if they occur we have very little idea of what is going on, why the best is to leave here and now.

Go to Top of Page
   

- Advertisement -