开发者

Transact-SQL - how to prevent second batch from running if the first failed?

开发者 https://www.devze.com 2023-04-05 07:24 出处:网络
In a previous question, Problem with alter then update in try catch with tran using Transact-SQL, I found out that to get my SQL working I had to break it up into two batches. Here is the SQL for that

In a previous question, Problem with alter then update in try catch with tran using Transact-SQL, I found out that to get my SQL working I had to break it up into two batches. Here is the SQL for that:

USE PUK;
GO
BEGIN TRANSACTION;
BEGIN TRY

   -- - Modify RETRIEVAL_STAT
   alter table dbo.RETRIEVAL_STAT add
      SOURCE nvarchar(10) NULL,
      ACCOUNTNUMBER nvarchar(50) NULL,
开发者_StackOverflow社区      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

My question now is: how do I prevent the second batch from running if the first batch fails?

Thanks for any advice!

Rob :)


Following the additional information in your comment the problem you are having is because this is not a catchable error.

The parsing of the first batch failed due to a non existent object so the whole batch failed to execute (including your raiserror statement).

to give a simplified example

SELECT * FROM NonExistentTable

GO

SELECT 1 AS [SecondBatch]

Returns

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


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

A couple of ways around this would be to put each batch into a child scope using dynamic 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]')

Returns

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.

Or (as variables will be out of scope between batches) you could SET CONTEXT_INFO at the end of each batch and then check this at the start of the next batch.

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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号