Обработка ошибок в транзакциях

Завершено

Структурированная обработка исключений использует конструкцию TRY/CATCH для проверки ошибок и обработки ошибок. При использовании обработки исключений с транзакциями важно поместить ключевые слова COMMIT или ROLLBACK в правильное место в отношении блоков TRY/CATCH.

Фиксация транзакций

При использовании транзакций со структурированной обработкой исключений поместите ТРАНЗАКЦИЮ COMMIT внутри блока TRY, как показано в следующем примере кода:

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 

Откат транзакции

При использовании с структурированной обработкой исключений поместите ROLLBACK TRANSACTION в блок CATCH, как показано в следующем примере кода:

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

Чтобы избежать отката активной транзакции, используйте функцию XACT_STATE. XACT_STATE возвращает следующие значения:

Возвращаемое значение Значение
1 Текущий запрос имеет активную транзакцию пользователя, готовую к фиксации.
0 Нет активной транзакции.
-1 Текущий запрос имеет активную транзакцию пользователя, но произошла ошибка, которая привела к классификации транзакции как неуправляемой транзакции.

XACT_STATE можно использовать перед командой ROLLBACK, чтобы проверить, активна ли транзакция.

В следующем коде показана функция XACT_STATE, используемая в блоке CATCH, чтобы транзакция была откатена только при наличии активной пользовательской транзакции.

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;