Lidar com erros em transações

Concluído

O tratamento de exceção estruturado usa o constructo TRY/CATCH para testar erros e manipular erros. Ao usar o tratamento de exceções com transações, é importante colocar as palavras-chave COMMIT ou ROLLBACK no lugar correto em relação aos blocos TRY/CATCH.

Confirmar transações

Ao usar transações com tratamento de exceção estruturado, coloque COMMIT TRANSACTION dentro do bloco TRY como no seguinte exemplo de código:

BEGIN TRY
 BEGIN TRANSACTION
 	INSERT INTO dbo.Orders(custid, empid, orderdate)
	VALUES (68,9,'2006-07-12');
	INSERT INTO dbo.OrderDetails(orderid,productid,unitprice,qty)
	VALUES (1, 2,15.20,20);
 COMMIT TRANSACTION
END TRY 

Reverter transação

Quando usado com tratamento de exceção estruturado, coloque ROLLBACK TRANSACTION dentro do bloco CATCH como no exemplo de código a seguir:

BEGIN TRY
 BEGIN TRANSACTION;
 	INSERT INTO dbo.Orders(custid, empid, orderdate)
	VALUES (68,9,'2006-07-12');
	INSERT INTO dbo.OrderDetails(orderid,productid,unitprice,qty)
	VALUES (1, 2,15.20,20);
 COMMIT TRANSACTION;
END TRY
BEGIN CATCH
	SELECT ERROR_NUMBER() AS ErrNum, ERROR_MESSAGE() AS ErrMsg;
	ROLLBACK TRANSACTION;
END CATCH;

XACT_STATE

Para evitar reverter uma transação ativa, use a função XACT_STATE. XACT_STATE retorna os seguintes valores:

Valor de retorno Significado
1 A solicitação atual tem uma transação de usuário ativa e confirmável.
0 Nenhuma transação ativa.
-1 A solicitação atual tem uma transação de usuário ativa, mas ocorreu um erro que fez com que a transação fosse classificada como uma transação não compromissável.

XACT_STATE pode ser usado antes do comando ROLLBACK, para verificar se a transação está ativa.

O código a seguir mostra a função XACT_STATE sendo usada no bloco CATCH para que a transação só seja revertida se houver uma transação de usuário ativa.

BEGIN TRY
 BEGIN TRANSACTION;
 	INSERT INTO dbo.SimpleOrders(custid, empid, orderdate) 
	VALUES (68,9,'2006-07-12');
	INSERT INTO dbo.SimpleOrderDetails(orderid,productid,unitprice,qty) 
	VALUES (1, 2,15.20,20);
 COMMIT TRANSACTION;
END TRY
BEGIN CATCH
	SELECT ERROR_NUMBER() AS ErrNum, ERROR_MESSAGE() AS ErrMsg;
	IF (XACT_STATE()) <> 0
    	BEGIN
        ROLLBACK TRANSACTION;
    	END;
	ELSE .... -- provide for other outcomes of XACT_STATE()
END CATCH;