错误,SQL后继续INSERT

时间:2014-08-15 12:24:52

标签: sql-server tsql error-handling insert try-catch

我在T-SQL中编写了一些异常/错误处理。

目标是继续插入操作,即使其中一个插入导致错误。

当前代码如下所示:

INSERT INTO targettable
   SELECT       
      *, GETDATE() 
  FROM      
      table_log l
  LEFT JOIN 
      someothertable m ON l.id = m.id
  WHERE 
      l.actiontype = 'insert' 

问题:有时,表table_log中存在错误的行/条目。这会导致整个插入操作回滚。我希望服务器在发生错误后继续执行插入操作。

我的想法:我可以使用游标单独处理每个插入。但据我所知,这在性能方面会很糟糕。我还可以使用ignore_dup_keyXACT_ABORT OFF。但我强烈怀疑我们的DBA会允许这样做。另外,我也不认为这也是一个很好的解决方案。

这是另一个想法:

DECLARE @rowcount int 

SET @rowcount = (SELECT COUNT(*) FROM table_log l WHERE actiontype = 'insert')


    BEGIN TRY
        WHILE @rowcount > 0
        BEGIN 

                looppoint:

                INSERT INTO target_table
                SELECT somecolumn, GETDATE() 
                    FROM        table_log l
                    LEFT JOIN   some_other_table m
                        ON  l.id = m.id
                    WHERE   l.actiontype = 'insert' AND
                            l.id NOT IN 
                            (SELECT id 
                            FROM noinsert_table)

                SET @rowcount = @rowcount -1

        END         
    END TRY
    BEGIN CATCH

        execute sp_some_error_catching_procedure

        INSERT INTO noinsert_table
        SELECT SCOPE_IDENTITY()

        SET @rowcount = @rowcount -1

        GOTO looppoint

    END CATCH

基本上,我想捕获导致错误的行并使用此信息在下一个循环中从插入中排除行。但是我不确定这是否会奏效,我不认为SCOPE_IDENTITY会给我一个失败行的ID,只有成功的行。此外,这似乎过于复杂,容易出现其他问题。

如果有人有提示,我很乐意听到。

1 个答案:

答案 0 :(得分:1)

为什么不在插入数据之前或作为插入选择的一部分清理数据?这样,您只是尝试插入您知道将适合您要插入的表的参数的数据。然后你仍然可以使用基于集合的插入。

顺便说一下,请永远不要写那样的代码。您应始终始终在语句的插入部分和select中指定插入中的列,并且永远不要使用select *。如果有人重新排列表中的列,您的插入将中断或更糟,不会中断但将数据放入错误的列中。如果有人在插入到选定表中时不需要添加列,则插入将中断。这种事情是一个SQL反模式。