2011-12-21 3 views
1

Итак, у нас есть несколько хранимых процессов, которые используются во время утренней работы SQL, и procs вызывается последовательно. В случае, если один из запросов внутри proc проваливается, у нас есть ловушка ошибки/logging, которую мы делаем для каждого запроса, чтобы мы точно знали, что произошло. Но проблема в том, что некоторые из этих процессов очень трудно начать, если что-то не удалось, поэтому я думаю о внедрении TRANSACTION в каждом сохраненном proc.Операция SQL Server с несколькими обновлениями, вставки

Текущая процедура похожа на это:

CREATE PROCEDURE [dbo].[spStep01] 
( 
    @Return_Message  Varchar(1024) OUT  -- Error messages returned to the calling program 
) 
AS 
BEGIN 

SET NOCOUNT ON; 

DECLARE @ErrorCode    int 
DECLARE @ApplicationNumber  int    
DECLARE @TaskNumber    int    
DECLARE @TaskCompleted   smallint   
DECLARE @TaskFailed    smallint   
DECLARE @TaskRunning   smallint   
DECLARE @ErrorSeverity   smallint   
DECLARE @ErrorState    smallint   

SELECT @ErrorCode = @@ERROR 
SELECT @ApplicationNumber = 10     
SELECT @TaskNumber   = 1 
SELECT @TaskCompleted  = 0 
SELECT @TaskFailed   = -1 
SELECT @TaskRunning   = 1 
SELECT @ErrorSeverity  = 16 
SELECT @ErrorState   = 1 

/*************************************************************************** 
* first insert 
***************************************************************************/ 
    BEGIN TRY 
     INSERT INTO ... 
    END TRY 
    BEGIN CATCH 
     SELECT @Return_Message = 'FAILED - first insert did not populate' 
     EXEC dbo.spTrackTask '', @ApplicationNumber, @TaskNumber, @TaskFailed, @Return_Message  
     RAISERROR (@Return_Message, @ErrorSeverity, @ErrorState) 
     RETURN 
    END CATCH 

/*************************************************************************** 
* second insert 
***************************************************************************/ 
    BEGIN TRY 
     INSERT INTO ... 
    END TRY 
    BEGIN CATCH 
     SELECT @Return_Message = 'FAILED - second insert did not populate' 
     EXEC dbo.spTrackTask '', @ApplicationNumber, @TaskNumber, @TaskFailed, @Return_Message  
     RAISERROR (@Return_Message, @ErrorSeverity, @ErrorState) 
     RETURN 
    END CATCH 


/*************************************************************************** 
* Procedure has completed successfully 
***************************************************************************/ 
    SELECT @Return_Message = 'SUCCESS - Inserts were complete' 
    EXEC dbo.spTrackTask '', @ApplicationNumber, @TaskNumber, @TaskCompleted, @Return_Message 


/************************************* 
* Get the Error Message for @@Error 
*************************************/ 
    IF @ErrorCode <> 0 
    BEGIN 
     SELECT @Return_Message = [Description]  -- Return the SQL Server error 
      FROM master.dbo.SYSMESSAGES 
     WHERE error = @ErrorCode 
    END 

/************************************* 
* Return from the Stored Procedure 
*************************************/ 
    RETURN @ErrorCode        -- =0 if success, <>0 if failure 

END 

Что я пытаюсь определить, если я обернуть все TRY/CATCH блоков в TRANSACTION и возникает ошибка, если она будет откатить все. Я посмотрел на SO и нашел несколько examples одного блока TRY/CATCH, но у нас было бы несколько в большинстве хранимых процессов. У меня нет большого опыта работы с транзакциями, поэтому я не уверен на 100% как правильно его реализовать в этом случае.

Будет ли упаковка в TRANSACTION работать? Или есть лучший способ сделать это?

ответ

5

Как об этом

BEGIN TRANSACTION tx 
BEGIN TRY 
    @CurrentStep = "First Insert" 
    INSERT ... 

    @CurrentStep = "Second Insert" 
    INSERT ...Second 

    IF @@TRANSCOUNT > 0 
    BEGIN --SUCCESS, nothing failed, now I can commit!! 
    SELECT @Return_Message = 'SUCCESS - Inserts were complete' 
    EXEC dbo.spTrackTask '', @ApplicationNumber, @TaskNumber, @TaskCompleted, @Return_Message 
    COMMIT TRANSACTION tx; -- now everything is committed 
    END 
END TRY 

BEGIN CATCH 
    IF @@TRANSCOUNT > 0 --something failed 
    BEGIN 
    IF @CurrentStep = 'First Insert' 
     SELECT @Return_Message = 'FAILED - first insert did not populate' 
    ELSE IF @CurrentStep = 'Second Insert' 
     SELECT @Return_Message = 'FAILED - second insert did not populate' 

    EXEC dbo.spTrackTask '', @ApplicationNumber, @TaskNumber, @TaskFailed, @Return_Message  
    RAISERROR (@Return_Message, @ErrorSeverity, @ErrorState) 

    ROLLBACK TRAN tx; -- everything is rolled back 
    END 
END CATCH 

Надеется, что это делает трюк для вас, помните, что все внутри транзакции должно быть совершен или откатом в одном месте, в противном случае вы лучше иметь несколько транзакций.

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