Несколько пакетов в транзакции SQL - PullRequest
0 голосов
/ 05 июня 2019

Я хочу создать несколько хранимых процедур (или пользовательских функций) внутри транзакции.CREATE PROCEDURE оператор должен быть единственным оператором в пакете, поэтому я должен использовать следующий шаблон:

BEGIN TRANSACTION MyTransaction

    USE MyDatabase
    GO

    CREATE PROCEDURE A
    AS
        -- The body of procedure A
    GO

    CREATE PROCEDURE B
    AS
        -- The body of procedure B
    GO

    CREATE PROCEDURE C
    AS
        -- The body of procedure C
    GO

COMMIT TRANSACTION MyTransaction

Проблема возникает, если в одном из пакетов возникает ошибка.Например, если ошибка возникает во время создания процедуры B , MyTransaction с процедурами A и B будет отменен.Но скрипт продолжит работать.Таким образом, будет создана процедура C .

Также невозможно пропустить инструкцию, используя проверку счетчика GOTO и @@error, поскольку она не может перейти к метке вне пакетав котором находится GOTO.

Как предотвратить изменения базы данных при возникновении ошибки?

1 Ответ

1 голос
/ 05 июня 2019

Вы можете попробовать сделать что-то подобное с SET XACT_ABORT ON .

IF EXISTS (SELECT * FROM tempdb..sysobjects WHERE id=OBJECT_ID('tempdb..#tmpErrors')) DROP TABLE #tmpErrors
GO
CREATE TABLE #tmpErrors (Error int)
GO
SET XACT_ABORT ON
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
GO
PRINT N'Creating [Proc A]'
GO
-------------------------------------------------------------------------
CREATE PROCEDURE A
    AS
        -- The body of procedure A
    GO
-------------------------------------------------------------------------

IF @@ERROR<>0 AND @@TRANCOUNT>0 ROLLBACK TRANSACTION
GO
IF @@TRANCOUNT=0 BEGIN INSERT INTO #tmpErrors (Error) SELECT 1 BEGIN TRANSACTION END
GO
PRINT N'Creating [Proc B]'
GO
-------------------------------------------------------------------------
CREATE PROCEDURE B
    AS
        -- The body of procedure B
    GO
-------------------------------------------------------------------------
IF @@ERROR<>0 AND @@TRANCOUNT>0 ROLLBACK TRANSACTION
GO
IF @@TRANCOUNT=0 BEGIN INSERT INTO #tmpErrors (Error) SELECT 1 BEGIN TRANSACTION END
GO
IF EXISTS (SELECT * FROM #tmpErrors) ROLLBACK TRANSACTION
GO
IF @@TRANCOUNT>0 BEGIN
PRINT 'The database update succeeded'
COMMIT TRANSACTION
END
ELSE PRINT 'The database update failed'
GO
DROP TABLE #tmpErrors
GO
...