Prefiro recomendar um padrão como o de Tratamento de exceções e transações aninhadas :
create procedure [usp_my_procedure_name]
as
begin
set nocount on;
declare @trancount int;
set @trancount = @@trancount;
begin try
if @trancount = 0
begin transaction
else
save transaction usp_my_procedure_name;
-- Do the actual work here
lbexit:
if @trancount = 0
commit;
end try
begin catch
declare @error int, @message varchar(4000), @xstate int;
select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
if @xstate = -1
rollback;
if @xstate = 1 and @trancount = 0
rollback
if @xstate = 1 and @trancount > 0
rollback transaction usp_my_procedure_name;
raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
end catch
end
Esse padrão verifica o XACT_STATE()
bloco catch para se proteger contra transações não confirmadas :
Transações não confirmadas e XACT_STATE
Se um erro gerado em um bloco TRY fizer com que o estado da transação atual seja invalidado, a transação será classificada como uma transação não confirmada. Um erro que normalmente encerra uma transação fora de um bloco TRY faz com que uma transação entre em um estado não comprometível quando o erro ocorre dentro de um bloco TRY. Uma transação não confirmada pode executar apenas operações de leitura ou uma TRANSAÇÃO ROLLBACK. A transação não pode executar nenhuma instrução Transact-SQL que geraria uma operação de gravação ou uma COMMIT TRANSACTION. A função XACT_STATE retornará um valor de -1 se uma transação tiver sido classificada como uma transação não comprometida. Quando um lote é finalizado, o Mecanismo de Banco de Dados reverte todas as transações não confirmadas ativas. Se nenhuma mensagem de erro foi enviada quando a transação entrou em um estado não confirmado, quando o lote terminar, uma mensagem de erro será enviada ao aplicativo cliente. Isso indica que uma transação não confirmada foi detectada e revertida.
Seu código está procurando @@TRANCOUNT
em locais onde não pode ser 0, ele usa uma mistura de mensagens informativas PRINT e conjuntos de resultados SELECT para se comunicar com sucesso, e não trata de erros recuperáveis. Idealmente, as exceções devem se propagar para o cliente, nesse caso, para o trabalho do agente (ou seja, sua captura deve aumentar novamente).