SQL Server 中的事务和@@Error 函数
Posted
技术标签:
【中文标题】SQL Server 中的事务和@@Error 函数【英文标题】:Transactions and @@Error function in SQL Server 【发布时间】:2020-09-22 03:36:30 【问题描述】:我只是想检查一下我放置@@Error
和Begin/Commit tran的位置是否正确?
我不确定是否应该使用 Begin Tran
而不是 DELETE
语句? @@ERROR
有什么意义吗?
谢谢!
CREATE PROCEDURE spDeleteAnInactiveEmployee
@TrainerID int,
@EActive char (1)
AS
BEGIN TRY
BEGIN TRAN
IF (SELECT COUNT(*) FROM EmployeeDetails ed
WHERE TrainerID = @TrainerID) = 0
RAISERROR ('Trainer details were not deleted. Trainer ID does not exist.', 16, 1)
IF EXISTS (SELECT * FROM EmployeeDetails ed
WHERE TrainerID = @TrainerID AND EActive = 'Y')
RAISERROR ('Trainer details were not deleted. Trainer is still active.', 16, 1)
DELETE FROM [EmployeeDetails]
WHERE TrainerID = @TrainerID AND EActive = 'N'
IF @@ERROR = 0
COMMIT TRAN
BEGIN
PRINT 'Employee ID' + CAST (@TrainerID AS VARCHAR) + ' was successfully deleted.'
END
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_STATE() AS ErrorState,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
IF (XACT_STATE()) = -1
BEGIN
PRINT 'Transaction was not committed'
ROLLBACK TRANSACTION;
END;
IF (XACT_STATE()) = 1
BEGIN
PRINT 'Transaction was committed'
COMMIT TRANSACTION;
END;
END CATCH;
GO
【问题讨论】:
为什么在这里选择错误?THROW
ing 它不是更好吗?还有为什么COMMIT
交易出错?一般来说,您不想在出错时COMMIT
。
我没有看到@@ERROR
签入代码,只有正常的结构化处理。我建议 1) 在 proc 的开头指定 SET XACT_ABORT ON;
以确保在查询超时的情况下立即回滚 2) 将 catch 块更改为简化的 IF @@TRANCOUNT > 0 ROLLBACK; THROW;
(假设 SQL 2012 或更高版本)以回滚 tran 和重新提出原来的错误。
对不起,我想说的是@@Error 而不是@@Rowcount。
does the @@ERROR make any sense at all
- 不,因为在 try
块中,raiserror
将立即跳转到 catch
。在try
块之外,它将继续并到达您的@@error
。
【参考方案1】:
当你使用 TRY/CATCH 时,@@ERROR 是不必要的。在 TRY/CATCH 之前,您必须在每个可能失败的语句之后检查 @@ERROR,并使用 GOTO 将控制流强制到错误标签。
所以这应该是这样的:
CREATE PROCEDURE spDeleteAnInactiveEmployee
@TrainerID int,
@EActive char (1)
AS
BEGIN
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRAN
IF (SELECT COUNT(*) FROM EmployeeDetails ed
WHERE TrainerID = @TrainerID) = 0
RAISERROR ('Trainer details were not deleted. Trainer ID does not exist.', 16, 1)
IF EXISTS (SELECT * FROM EmployeeDetails ed
WHERE TrainerID = @TrainerID AND EActive = 'Y')
RAISERROR ('Trainer details were not deleted. Trainer is still active.', 16, 1)
DELETE FROM [EmployeeDetails]
WHERE TrainerID = @TrainerID AND EActive = 'N'
COMMIT TRAN
PRINT 'Employee ID' + CAST (@TrainerID AS VARCHAR) + ' was successfully deleted.'
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK;
THROW;
END CATCH;
END
【讨论】:
以上是关于SQL Server 中的事务和@@Error 函数的主要内容,如果未能解决你的问题,请参考以下文章