我们有一个数据导入系统,我们正在处理 CSV 文件,每个文件都包含一组必须单独验证和处理的记录。如果它们由于某种原因失败,它们会被标记为错误,然后我们继续下一条记录。它们可能因逻辑错误或数据库错误(例如重复键或外键错误)而失败。
处理数据的存储过程要么从客户端应用程序调用,要么从代理作业调用。不同之处在于应用程序将创建事务,而作业在调用 proc 之前不会。
SET NOCOUNT ON;
SET XACT_ABORT OFF;
DECLARE @trancount_in INT,
@xstate INT,
@Row INT,
@MaxRows INT
SET @trancount_in = @@trancount
-- CODE: import data into temp table
select @Row = 1,
@MaxRows = @@Rowcount
IF @transcount_in = 0
BEGIN TRANSACTION
while @Row <= @MaxRows
-- CODE: Get data record from table
begin try
save transaction myproc
-- CODE: validate and process record
end try
begin catch
SELECT @xstate = XACT_STATE()
IF @xstate = -1 BEGIN
ROLLBACK
Raiserror('error',16,1)
END
IF @xstate = 1 and @@Trancount = 0 BEGIN
ROLLBACK
Raiserror('error',16,1)
END
IF @xstate = 1 and @@Trancount > 0
ROLLBACK TRANSACTION myproc
-- CODE: update import record with error here
end catch
set @Row = @Row + 1
End
IF @transcount_in = 0
COMMIT
到目前为止相当简单,但是查看大量文档,它说您应该在 catch 块中检查 xact_state 是否为 -1,但我不希望此时事务失败。我只想继续导入的下一行。因此,如果 xact_abort 关闭,我们会在 catch 块中获得 -1 的 xact_state 吗?
我知道 catch 实际上并没有捕获所有错误,但是我发现如果您使用 try catch 块创建父 proc,那么它将捕获比实际 proc 中的块更多的错误。所以我会将循环逻辑移动到父进程,然后在当前进程中进行处理。
我还应该做些什么来减轻可能发生的任何错误?
希望这不会太混乱。干杯阿德里安