这是我编码的简单测试。
SET XACT_ABORT ON
BEGIN TRANSACTION
GO
CREATE PROCEDURE [usp_MyTest1]
AS
GO
CREATE PROCEDURE [usp_MyTest1]
AS
GO
CREATE PROCEDURE [usp_MyTest2]
AS
GO
COMMIT TRANSACTION
我的理解是,由于我有SET XACT_ABORT ON
,当第二个创建过程失败时,整个事务将回滚。相反,只回滚错误的事情(第一个创建过程)被回滚,最后一个创建过程执行得很好。然后我收到一条消息The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
我看到人们对RAISEERROR存在问题,但XACT_ABORT的文档说RAISEERROR并不认可XACT_ABORT。但是,这并未提及任何有关错误的信息,例如创建不遵守XACT_ABORT的重复过程。
https://docs.microsoft.com/en-us/sql/t-sql/statements/set-xact-abort-transact-sql
THROW声明表示SET XACT_ABORT RAISERROR没有。新应用程序应使用THROW而不是RAISERROR。
这与SQL Server 2012有关,如果相关的话。
答案 0 :(得分:2)
回滚事务。
你可以用
清楚地看到这一点SET XACT_ABORT ON
BEGIN TRANSACTION
GO
SELECT @@TRANCOUNT, 'Point1'
GO
CREATE PROCEDURE [usp_MyTest1] AS
GO
SELECT @@TRANCOUNT, 'Point2'
GO
CREATE PROCEDURE [usp_MyTest1] AS
GO
/*
The earlier transaction has now been rolled back and
now running outside an explicit transaction. @@TRANCOUNT is 0
*/
SELECT @@TRANCOUNT, 'Point3'
GO
CREATE PROCEDURE [usp_MyTest2] AS
GO
SELECT @@TRANCOUNT, 'Point4'
GO
/*Nothing to commit so error*/
COMMIT TRANSACTION
返回
当您到达第3点时,事务已被回滚(包括初始创建usp_MyTest1
),并且usp_MyTest2
的创建发生在新的auto commit transaction中。因此,最终结果是数据库包含usp_MyTest2
而不是usp_MyTest1
,假设一开始就没有。
这也是你最后也看到错误的原因
消息3902,级别16,状态1,行19 COMMIT TRANSACTION请求 没有相应的BEGIN TRANSACTION。
要在发生错误并且回滚事务后终止脚本执行(而不是犁开并执行后续批处理),最可靠的方法是在SSMS中启用sqlcmd模式并将其添加到脚本的顶部{ {1}}