我想在一个事务中创建几个存储过程(或用户定义的函数)。 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 时发生错误,则将回滚包含过程 A 和 B 的MyTransaction
。但是该脚本将继续运行。因此,将创建过程 C 。
同样也无法使用GOTO
和@@error
计数器检查来跳过该语句,因为它无法转到放置GOTO
的批处理之外的标签。
如果发生错误,如何防止任何数据库更改?
答案 0 :(得分:1)
您可以尝试设置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