0

我有一个从表中获取数据并将其插入临时表的过程。然后该过程在 while 循环中一一验证。

例如:我有 50 行,第一行失败。在这种情况下,我希望程序继续处理剩余的 49 行。

我在插入语句中强制出错,并且我把它放在它下面,@@error <> 0但没有进入 if 块。

但是过程结束并且不会继续执行下一个要执行的语句。

我正在从查询分析器运行该过程,并使用 print 'line 1' 等放置消息。

谢谢您的帮助。

这是一个类似的例子

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'
4

1 回答 1

1

很可能您在导致错误的语句和IF检查之间有一个语句。在这里简化错误处理逻辑(因为它是一个非常庞大的主题)并忽略批处理中止和连接终止错误......

这会产生错误消息和'Uh oh'

SELECT 1/0;

PRINT 'Uh oh';

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

由于@@ERROR在每条语句之后都被重置,它不再是非零的,并且IF不会进入块。虽然以下内容按预期工作,因为我们@@ERROR在故障声明之后立即进行检查:

SELECT 1/0;

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

如果您确实需要在两者之间做一些事情,则可以将值存储在变量中:

DECLARE @err INT;

SELECT 1/0;

SELECT @err = @@ERROR;

PRINT 'Uh oh';

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

这将执行这两个PRINT命令。

编辑

由于您现在添加了代码,我可以进一步了解为什么这在您的情况下不起作用。无效对象是严重性 16 错误:

消息 208,级别 16,状态 1,过程 procx,第 110 行
无效的对象名称“测试”。

现在,根据文档,严重性 16 不会中止批处理(仅 19 及以上),但这并不意味着这总是正确的。例如,请参阅这篇博文,其中解释了在某些情况下 sev16可以中止批处理。除了 (a) 不创建引用不存在的对象的存储过程或 (b) 升级到现代版本的 SQL Server对错误处理进行了更多思考)。

于 2013-10-23T20:08:57.907 回答