我的同事在程序中有这个:
BEGIN TRAN
--Some deletes and inserts
IF(@@error <> 0)
BEGIN
ROLLBACK TRAN
RETURN
END
COMMIT TRAN
我在存储过程中有另一个只是:
BEGIN TRANSACTION
--Some deltes and inserts
COMMIT TRANSACTION
我已经测试过并发现我的程序总是在错误期间(例如更改列数据类型等测试)回滚所有内容而不显式编码回滚。另外我已经读过,对于SQL Server 2005及更高版本,使用@@error
条件已过时。
您认为为SQL Server 2008 R2及更高版本执行事务的正确方法是什么?感谢
答案 0 :(得分:12)
是,ROLLBACK
是必要的!
我会基于此模板为SQL Server 2005和更新版本执行存储过程:
BEGIN TRANSACTION
BEGIN TRY
-- put your T-SQL commands here
-- if successful - COMMIT the work
COMMIT TRANSACTION
END TRY
BEGIN CATCH
-- handle the error case (here by displaying the error)
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage
-- in case of an error, ROLLBACK the transaction
ROLLBACK TRANSACTION
-- if you want to log this error info into an error table - do it here
-- *AFTER* the ROLLBACK
END CATCH
答案 1 :(得分:4)
@@ ERROR变量存在问题。 这是一个全局变量,因此如果您正在执行以下操作:
BEGIN TRAN
--inserts
--deletes
--updates
-- last operation
IF(@@error <> 0)
BEGIN
ROLLBACK TRAN
RETURN
END
COMMIT TRAN
@@ error仅包含上一次操作的结果。因此,这段代码可以掩盖先前操作中的错误。
我的建议是,如果您可以在应用程序级别管理事务,请在应用程序级别执行。 在服务器端处理错误不适用于胆小的人,也不会改善你的应用程序的内部滥用。
答案 2 :(得分:0)
在数据库中创建以下过程,然后在catch块中创建,exec RethrowError
。
关于这一点的好处是你不必从主存储过程
CREATE PROCEDURE [dbo].[RethrowError] AS
-- Return if there is no error information to retrieve.
IF ERROR_NUMBER() IS NULL
RETURN;
DECLARE
@ErrorMessage NVARCHAR(4000),
@ErrorNumber INT,
@ErrorSeverity INT,
@ErrorState INT,
@ErrorLine INT,
@ErrorProcedure NVARCHAR(200);
-- Assign variables to error-handling functions that
-- capture information for RAISERROR.
SELECT
@ErrorNumber = ERROR_NUMBER(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE(),
@ErrorLine = ERROR_LINE(),
@ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');
-- Building the message string that will contain original
-- error information.
SELECT @ErrorMessage =
N'Error %d, Level %d, State %d, %s, Line %d' + ERROR_MESSAGE();
-- Raise an error: msg_str parameter of RAISERROR will contain
-- the original error information.
RAISERROR
(
@ErrorMessage,
@ErrorSeverity,
1,
@ErrorNumber, -- parameter: original error number.
@ErrorSeverity, -- parameter: original error severity.
@ErrorState, -- parameter: original error state.
@ErrorProcedure, -- parameter: original error procedure name.
@ErrorLine -- parameter: original error line number.
);
GO
CREATE PROCEDURE YourProcedure
AS
BEGIN TRANSACTION
BEGIN TRY
--Put your code in here
END TRY
BEGIN CATCH
EXEC RethrowError
END CATCH
END