使用 THROW througout usp 进行数据验证,回滚?

Use THROW througout usp for data validation, with rollback?

我有一个查询可以预先检查来自应用程序的数据,以确保应用程序没有传递错误数据。如果有一块坏数据,则使用 THROW 引发错误。这是否让我的交易保持开放状态,因为我当时没有碰到 catch 块?如果是这样,我将如何处理?

例如:

BEGIN TRY
BEGIN TRANSACTION

IF NOT EXISTS(SELECT 1 FROM dbo.lutCode WHERE ID = @CodeID)
BEGIN
  THROW('50001','Test Error',1)
END

UPDATE emp
SET emp.CodeID = @CodeID
WHERE emp.ID = @EmployeeID

IF XACT_STATE() = 1 COMMIT TRANSACTION

END TRY

BEGIN CATCH

IF XACT_STATE() = -1 ROLLBACK TRANSACTION

THROW;

END CATCH

查询比这复杂很多,在实际查询中,IF EXISTS 确实需要在事务中,所以将它放在事务之外不是一个选项。

我会以不同的方式处理这个问题,

在完成验证之前不要打开事务,如果验证失败,则会在 try 块中引发错误,控制将跳转到 catch 块 ignoring/skipping try 块中的其余代码。

我添加了检查 IF(@@TRANCOUNT <> 0) ROLLBACK TRAN,因为在验证期间可能会出现错误,在这种情况下,交易将永远不会打开。

只有在执行更新语句时出现问题时,控件才会跳转到 catch 块而不提交事务,然后回滚并执行其余的错误日志记录。

BEGIN TRY

  -- do validatiion before openning transaction
  IF NOT EXISTS(SELECT 1 FROM dbo.lutCode WHERE ID = @CodeID)
    BEGIN
      RAISERROR('Test Error',16, 1)
    END

-- if test passed now open transaction
 BEGIN TRANSACTION;

    UPDATE emp
    SET emp.CodeID = @CodeID
    WHERE emp.ID = @EmployeeID

-- commit transaction if nothing gone wrong
 COMMIT TRANSACTION;
END TRY

BEGIN CATCH
 -- Rollback transaction if something went wrong 
 -- after you opened the trasaction 

 IF (@@TRANCOUNT <> 0)
  BEGIN
    ROLLBACK TRANSACTION;
  END

-- Other error logging
 SELECT ERROR_LINE() AS Errorline
       ,ERROR_MESSAGE() AS ErrorMessage
       ,ERROR_NUMBER()  AS ErrorNumber .......

END CATCH

将 catch 块中的语句更改为:

if xact_state() = 1 rollback tran

-1 仅在非常特殊的情况下出现,我认为您不会在查询中遇到这种情况。如果您将其更改为在任何非 0 的 xact_state 上回滚,您应该停止挂起事务。

此外,我认为您不应该在 TRY 块中使用 THROW;只是捕获块。您想使用 raiserror() 在 try 块中触发错误,然后如果您愿意,在 catch 块中使用 throw。