Transact-SQL - как предотвратить запуск второго пакета, если первый потерпел неудачу? - PullRequest
2 голосов
/ 17 сентября 2011

В предыдущем вопросе Проблема с alter и обновлением в try catch с trans с использованием Transact-SQL , я обнаружил, что для работы моего SQL мне пришлось разбить его на две части.Вот SQL для этого:

USE PUK;
GO
BEGIN TRANSACTION;
BEGIN TRY

   -- - Modify RETRIEVAL_STAT
   alter table dbo.RETRIEVAL_STAT add
      SOURCE nvarchar(10) NULL,
      ACCOUNTNUMBER nvarchar(50) NULL,
      PUK nvarchar(20) NULL;

END TRY
BEGIN 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;
    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION;
END CATCH;
IF @@TRANCOUNT > 0
    COMMIT TRANSACTION;
GO


USE PUK;
GO
BEGIN TRANSACTION;
BEGIN TRY

   -- transform logic.
   UPDATE      dbo.RETRIEVAL_STAT
   SET         SOURCE = 'ABC',
               ACCOUNTNUMBER = ABC.ACCOUNTNUMBER,
               PUK = ABC.PUK
   FROM        RETRIEVAL_STAT RS
   INNER JOIN  ABC
   ON          RS.SERVICE_NUMBER = ABC.SERVICENUMBER;

  --- ... snip

END TRY
BEGIN 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;
    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION;
END CATCH;
IF @@TRANCOUNT > 0
    COMMIT TRANSACTION;
GO

Теперь у меня вопрос: как предотвратить запуск второго пакета в случае сбоя первого пакета?

Спасибо за любой совет!

Роб:)

1 Ответ

1 голос
/ 18 сентября 2011

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

Не удалось выполнить синтаксический анализ первого пакета из-за несуществующего объекта, поэтому не удалось выполнить весь пакет (включая оператор raiserror).

для упрощенного примера

SELECT * FROM NonExistentTable

GO

SELECT 1 AS [SecondBatch]

Возвращает

Msg 208, Level 16, State 1, Line 3
Invalid object name 'NonExistentTable'.


SecondBatch
-----------
1

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

BEGIN TRY
EXEC('SELECT * FROM NonExistentTable')
END TRY
BEGIN CATCH
RAISERROR('Oh no a fatal error', 20, -1) WITH LOG
END CATCH

EXEC('SELECT 1 AS [SecondBatch]')

Возвращает

Msg 2745, Level 16, State 2, Line 5
Process ID 55 has raised user error 50000, severity 20. SQL Server is terminating this process.
Msg 50000, Level 20, State 1, Line 5
Oh no a fatal error
Msg 0, Level 20, State 0, Line 0
A severe error occurred on the current command.  The results, if any, should be discarded.

Или (поскольку переменные будут выходить за рамки между партиями), вы можете SET CONTEXT_INFO в конце каждого пакета и затем проверить это в начале следующего пакета.

BEGIN TRY
SELECT * FROM NonExistentTable
SET CONTEXT_INFO 1
END TRY
BEGIN CATCH

END CATCH
GO
IF CONTEXT_INFO() <> 1
   RETURN

BEGIN TRY
SELECT 1 AS [SecondBatch]
SET CONTEXT_INFO 2
END TRY
BEGIN CATCH   
END CATCH


GO

IF CONTEXT_INFO() <> 2
   RETURN

BEGIN TRY
SELECT 1 AS [ThirdBatch]
SET CONTEXT_INFO 3
END TRY
BEGIN CATCH   
END CATCH
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...