Я бы попытался иметь только один 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