Обработка транзакций SQL Server - PullRequest
2 голосов
/ 04 сентября 2011

Я выполняю следующую хранимую процедуру и получаю сообщение об ошибке

Запрос COMMIT TRANSACTION не имеет соответствующей BEGIN TRANSACTION.

что мне не хватаетздесь?

CREATE PROCEDURE spImportData
AS

BEGIN TRANSACTION

BEGIN TRY 
   SET IDENTITY_INSERT PINCDOCControlNew..tblActionType ON
END TRY
BEGIN CATCH
   PRINT 'IDENTITY_INSERT IS ON'
END CATCH
GO

BEGIN TRY
   INSERT INTO PINCDOCControlNew..tblActionType(ActionTypeID,ActionType,ActionTypeDescription)
      SELECT ActionTypeID,ActionType,ActionTypeDescription 
      FROM PINCDOCControlOld..tblActionType

   SET IDENTITY_INSERT PINCDOCControlNew..tblActionType OFF
END TRY
BEGIN CATCH
   SET IDENTITY_INSERT PINCDOCControlNew..tblActionType OFF
   EXECUTE usp_GetErrorInfo
END CATCH

BEGIN TRY
    SET IDENTITY_INSERT PINCDOCControlNew..tblArea ON
END TRY
BEGIN CATCH
    PRINT 'IDENTITY_INSERT IS ON'
END CATCH

GO

BEGIN TRY
    INSERT INTO PINCDOCControlNew..tblArea(AreaID,AreaDescription,AreaNo)
        SELECT AreaNo,AreaDescription,Area 
        FROM PINCDOCControlOld..tblArea

    SET IDENTITY_INSERT PINCDOCControlNew..tblArea OFF
END TRY
BEGIN CATCH
    SET IDENTITY_INSERT PINCDOCControlNew..tblArea OFF
    EXECUTE usp_GetErrorInfo
END CATCH

IF @@ERROR <> 0
BEGIN
    -- Rollback the transaction
    ROLLBACK

    -- Raise an error and return
    RAISERROR ('Error in inserting.', 16, 1)
    RETURN
 END
 COMMIT

Ответы [ 2 ]

7 голосов
/ 04 сентября 2011

что мне здесь не хватает?

У вас, вероятно, есть избыток, а не дефицит.Вам необходимо удалить операторы GO.

Единственная разумная интерпретация вашего сценария состоит в том, что он предназначен для того, чтобы быть частью определения хранимой процедуры spImportData.

Это заканчивается первым оператором GO (используется клиентскими инструментами для разделения пакетов), а остальные пакеты выполняются немедленно в транзакциях автоматической фиксации, так как явный BEGIN TRAN не был запущен,При достижении оператора COMMIT зафиксировать нечего, поэтому возникает ошибка.

4 голосов
/ 04 сентября 2011

Я бы попытался иметь только один BEGIN TRY .... END TRY блок, в котором у вас есть вся логика, которую вы хотите выполнить. Если что-то пойдет не так - где-нибудь в вашей логике - вы попадете в блок BEGIN CATCH.... END CATCH.

Начните транзакцию до BEGIN TRY, и у вас будет только COMMIT в качестве последнего оператора в вашем блоке TRY, а в вашем блоке CATCH будет выполнен откат.

Примерно так:

CREATE PROCEDURE dbo.spImportData
AS
    BEGIN TRANSACTION
    BEGIN TRY 
        SET IDENTITY_INSERT PINCDOCControlNew..tblActionType ON

        INSERT INTO 
            PINCDOCControlNew..tblActionType(ActionTypeID, ActionType, ActionTypeDescription)
            SELECT 
               ActionTypeID, ActionType, ActionTypeDescription 
            FROM 
              PINCDOCControlOld..tblActionType

        SET IDENTITY_INSERT PINCDOCControlNew..tblActionType OFF

        -- tblArea
        SET IDENTITY_INSERT PINCDOCControlNew..tblArea ON

        INSERT INTO 
             PINCDOCControlNew..tblArea(AreaID, AreaDescription, AreaNo)
           SELECT 
               AreaNo, AreaDescription, Area 
           FROM 
               PINCDOCControlOld..tblArea

        SET IDENTITY_INSERT PINCDOCControlNew..tblArea OFF

        COMMIT TRANSACTION
    END TRY
    BEGIN CATCH
       ROLLBACK TRANSACTION

       SET IDENTITY_INSERT PINCDOCControlNew..tblActionType OFF
       SET IDENTITY_INSERT PINCDOCControlNew..tblArea OFF

       EXECUTE usp_GetErrorInfo

       RAISERROR ('Error in inserting.', 16, 1)
    END CATCH

При таком подходе у вас есть ровно ОДНА BEGIN TRANSACTION и либо один соответствующий COMMIT TRANSACTION, либо единственный соответствующий ROLLBACK TRANSACTION

Обычно я также добавляю этот оператор SELECT в мой блок CATCH, чтобы получить сообщение об ошибке и код ошибки того, что пошло не так:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...