Question

I have a procedure that gets data from a table and inserts it into a temporary table. Then the procedure validates one by one in a while loop.

For example: I have 50 rows and the first row fails. In that case, I wish that the procedure continues processing the remaining 49 rows.

I'm forcing an error in an insert statement and and I put under it @@error <> 0 but does not enter if block.

But procedure ends and doesn't continues with the next statement to be executed.

I am running the procedure from Query Analyzer and put message with print 'line 1' etc etc.

Thank you for your help.

This is a similar example

create procedure procx
as

  declare
    @ind_max  int,
    @ind      int,
    @var_id   int,
    @var_name varchar(3)

  declare @table_x table
  (
    row_id    int identity(1,1),
    id_x      int,
    name_x    varchar(25),
    status_x  int
  )

  insert into @table_x values(1, 'xxx', 0)
  insert into @table_x values(2, 'yyy', 0)
  insert into @table_x values(3, 'zzz', 0)

  set @ind_max = 3
  set @ind = 1

  while (@ind <= @ind_max)
  begin

    print 'line 1'

    select @var_id   = id_x   ,
           @var_name = name_x
    from @table_x
    where row_id = @ind

    -- Forced error id_x is int field
    -- Doesn't show line2, line3 ...
    -- Msg 245, Level 16, State 1, Procedure procx, Line 160
    -- Syntax error converting the varchar value 'A' to a column of data type int.
    insert into test ( id_x , name_x )
    values ( 'A' , @var_name )

    if @@error != 0
    begin

      print 'line 2'
      goto next_row

      insert into log_test values(@var_id, 'Error')

    end

    print 'line 3'

    update @table_x
    set status_x = 1
    where row_id = @ind

    print 'line 4'

next_row:
    set @ind = @ind + 1

  end

  print 'line 5'
Was it helpful?

Solution

Most likely you have a statement in between the error-causing statement and the IF check. Simplifying the error handling logic here (since it is an extremely vast topic) and ignoring batch-aborting and connection-terminating errors...

This yields the error message and 'Uh oh':

SELECT 1/0;

PRINT 'Uh oh';

IF @@ERROR <> 0
BEGIN
  PRINT 'Error.';
END

Since @@ERROR gets reset after every statement, it is no longer non-zero, and the IF block does not get entered. While the following works as expected, because we are checking @@ERROR immediately after the trouble statement:

SELECT 1/0;

IF @@ERROR <> 0
BEGIN
  PRINT 'Error.';
END

If you do have stuff you need to do in between, you can store the value in a variable:

DECLARE @err INT;

SELECT 1/0;

SELECT @err = @@ERROR;

PRINT 'Uh oh';

IF @err <> 0
BEGIN
  PRINT 'Error.';
END

This will execute both PRINT commands.

EDIT

Since you now added your code, I can give further insight into why this isn't working in your case. Invalid object is a severity 16 error:

Msg 208, Level 16, State 1, Procedure procx, Line 110
Invalid object name 'test'.

Now, according to the documentation, severity 16 does not abort the batch (only 19 and above), but that doesn't mean this is always true. For example, see this blog post which explains that in some cases sev16 can abort the batch. I don't have a 2000 instance anywhere around to test this for certain or to investigate workarounds, other than (a) not creating stored procedures that reference objects that don't exist or (b) upgrading to a modern version of SQL Server that has put a little more thought into error handling).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top