2015-09-18 2 views
3

У меня есть хранимая процедура, которая находится в этом формате (упрощенный):сделка по-прежнему совершает после нарушения ограничения уникальности

SET XACT_ABORT ON 
GO 
BEGIN TRY 
BEGIN TRANSACTION myTransaction 
--multiple CRUD operations 
--insert statement inserts records into table with unique constraint. 

    IF (XACT_STATE()) = 1 
     BEGIN  
     COMMIT TRANSACTION myTransaction 
     RAISERROR ('TRANSACTION COMMITTED', 0, 1) WITH NOWAIT 
     RETURN 1 
     END 
END TRY 

BEGIN CATCH 
    IF (XACT_STATE()) = -1 
     BEGIN 
     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 

     ROLLBACK TRANSACTION myTransaction 
     RAISERROR ('TRANSACTION ROLLED BACK', 0, 1) WITH NOWAIT 
     RETURN 0 
     END 
    IF (XACT_STATE()) = 1 
     BEGIN   
     COMMIT TRANSACTION myTransaction 
     RAISERROR ('TRANSACTION COMMITTED', 0, 1) WITH NOWAIT 
     RETURN 1 
     END 
END CATCH 

Я пытаюсь решить проблему, где SP пытается вставлять записи в таблицу с уникальным ограничением, и он терпит неудачу, поэтому он ничего не вставляет. Проблема в том, что это, похоже, не вызывает блокировку catch или не изменяет XACT_STATE(), чтобы отразить, что есть проблема. Что я делаю не так?

Желаемая функциональность заключалась бы в том, что если ограничение будет нарушено, вся транзакция завершится неудачно и будет отброшена.

+5

Почему вы добавляете механизм фиксации в блок catch? –

+0

Потому что, насколько я понимаю, существуют сценарии, в которых транзакция находится в состоянии commitable, но будет блокирован блок catch. Я не могу вспомнить, где я получил эту информацию, или какой сценарий может вызвать это. Я прочитал его в Интернете, который, как вы знаете, непогрешимый. – Jon

ответ

4

У вас есть сложная задача довольно простая, я бы просто полностью отказался от функции XACT_ABORT() и просто установил файл try..catch. что-то вроде ......

BEGIN TRY 
     BEGIN TRANSACTION myTransaction 
--multiple CRUD operations 
--insert statement inserts records into table with unique constraint. 


-- if an error occurs in any of the above statements the control will 
-- jump to Catch block and the Commit trans never gets executed 
     COMMIT TRANSACTION myTransaction 

END TRY 

BEGIN CATCH 
    IF @@TRANCOUNT > 0 
    BEGIN 
     ROLLBACK TRANSACTION myTransaction 
    END 

     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 

END CATCH 
+0

Это намного проще, спасибо. – Jon

6

Как вы используете

Set Xact_Abort On 

Мое понимание в том, что сделка уже откат к тому времени, вы получите любой Выгода части. Отказываться нечего.

Есть также кое-что, что я помню, когда бывают случаи, когда такой экземпляр вообще обходит Поймать.

+0

Это может иметь какое-то отношение к этому. Когда я изначально написал этот код, у меня не было XACT_ABORT ON. Я добавил этот бит кода сегодня, так что это могло вызвать проблемы. – Jon

Смежные вопросы