我们在生产环境中遇到了一个问题,其中只有前2个更新运行,而后2个没有运行。从BIDS(SQL服务器)运行以下脚本以确保运行4个sql更新语句中的每一个,我们可以实现什么?我们是否需要将整个内容包装在Try ..... Catch中?
下面基本上是我现在在生产中使用的最终工作代码。
SET XACT_ABORT ON;
GO
BEGIN TRANSACTION
-- Batch 0
BEGIN TRY
--There is a step prior to this step to delete table
Insert Into Table X (Field1, Field2, Field3)
Select
Field1
,Field2
,Field3
FROM Table Loans
END TRY
BEGIN CATCH
PRINT 'Error Number: ' + str(error_number()) ;
PRINT 'Line Number: ' + str(error_line());
PRINT error_message();
ROLLBACK TRANSACTION;
END CATCH;
GO
-- Batch 1
BEGIN TRY
-- Rollback transaction if error occurred
IF (XACT_STATE()) = -1
BEGIN
RAISERROR('The transaction is in an uncommittable state. Rolling back transaction.', 18, 3);
END;
-- Do not continue if the transaction was rolled back
IF (XACT_STATE()) = 0
BEGIN
RAISERROR('The transaction was rolled back.', 18, 1);
END;
--Update A Fields
Update X Table
Set X Field4 = A Field
From X Table
Left OUTER JOIN A Table
ON X Key = A Key
END TRY
BEGIN CATCH
PRINT 'Error Number: ' + str(error_number()) ;
PRINT 'Line Number: ' + str(error_line());
PRINT error_message();
IF (XACT_STATE()) <> 0
BEGIN
PRINT 'Rolling Back Transaction...';
ROLLBACK TRANSACTION;
END;
END CATCH;
GO
-- Batch 2
BEGIN TRY
-- Rollback transaction if error occurred
IF (XACT_STATE()) = -1
BEGIN
RAISERROR('The transaction is in an uncommittable state. Rolling back transaction.', 18, 3);
END;
-- Do not continue if the transaction was rolled back
IF (XACT_STATE()) = 0
BEGIN
RAISERROR('The transaction was rolled back.', 18, 1);
END;
--Update B Fields
Update X Table
Set X Field5 = B Field
From X Table
Left OUTER JOIN B Table
ON X Key = B Key
END TRY
BEGIN CATCH
PRINT 'Error Number: ' + str(error_number()) ;
PRINT 'Line Number: ' + str(error_line());
PRINT error_message();
IF (XACT_STATE()) <> 0
BEGIN
PRINT 'Rolling Back Transaction...';
ROLLBACK TRANSACTION;
END;
END CATCH;
GO
-- Batch 3
BEGIN TRY
-- Rollback transaction if error occurred
IF (XACT_STATE()) = -1
BEGIN
RAISERROR('The transaction is in an uncommittable state. Rolling back transaction.', 18, 3);
END;
-- Do not continue if the transaction was rolled back
IF (XACT_STATE()) = 0
BEGIN
RAISERROR('The transaction was rolled back.', 18, 1);
END;
--Update C Fields
Update X Table
Set X Field5 = C Field
From X Table
Left OUTER JOIN C Table
ON X Key = C Key
END TRY
BEGIN CATCH
PRINT 'Error Number: ' + str(error_number()) ;
PRINT 'Line Number: ' + str(error_line());
PRINT error_message();
IF (XACT_STATE()) <> 0
BEGIN
PRINT 'Rolling Back Transaction...';
ROLLBACK TRANSACTION;
END;
END CATCH;
GO
-- Batch 4
BEGIN TRY
-- Rollback transaction if error occurred
IF (XACT_STATE()) = -1
BEGIN
RAISERROR('The transaction is in an uncommittable state. Rolling back transaction.', 18, 3);
END;
-- Do not continue if the transaction was rolled back
IF (XACT_STATE()) = 0
BEGIN
RAISERROR('The transaction was rolled back.', 18, 1);
END;
--Update D Fields
Update X Table
Set X Field7 = D Field
From X Table
Left OUTER JOIN D Table
ON X Key = D Key
END TRY
BEGIN CATCH
PRINT 'Error Number: ' + str(error_number()) ;
PRINT 'Line Number: ' + str(error_line());
PRINT error_message();
IF (XACT_STATE()) <> 0
BEGIN
PRINT 'Rolling Back Transaction...';
ROLLBACK TRANSACTION;
END;
END CATCH;
GO
-- Commit transaction
IF XACT_STATE() = 1
BEGIN
COMMIT TRANSACTION;
PRINT 'Transaction committed.';
END;
答案 0 :(得分:2)
我会将其包装在事务中,如果出现问题,它将自动回滚更改。
BEGIN TRANSACTION
your tsql code...
COMMIT
在仍在使用事务的同时,将代码包装在try / catch中,然后可以选择/打印/记录错误。 Try...Catch (Transact-SQL)
答案 1 :(得分:1)
这一切都取决于您的生产环境如何处理服务器错误。
例如,如果第3次更新由于外键冲突而失败,则服务器将错误返回给客户端。客户处理它,但是它处理它。 中止,重试或忽略情况。根据实际问题,该批处理不一定要终止,因此,除非客户端采取行动,否则仍然可能执行第4次更新。
服务器还会将每个存储过程的退出状态返回给客户端,客户端可以自由地接受或忽略该退出状态。您也可以将整个内容包装在存储过程中。在每个UPDATE
之后,测试@@error
,然后返回是否已设置。
如果您的生产环境完全未知或不可靠,则可以调用自己的存储过程,并将其名称和返回状态写到另一个表中,可能还包括执行时间。然后,您可以查询该表以查看它是否成功。