【发布时间】:2016-07-19 14:21:37
【问题描述】:
我使用的是 SQLServer 2014,我有一个简单的数据库,其中有一个表,该表有一个 ID 和一个名为 data 的 varchar 列。当我运行以下语句时有一些奇怪的行为:
SET XACT_ABORT ON
BEGIN TRANSACTION
exec sp_executesql N'some nonsense'
insert into testTable values ('b')
COMMIT
SSMS 显示出现错误,因为我试图在 sp_executesql 调用中运行不正确的查询。但是,它也显示1 row(s) affected。如果我在 testTable 上运行选择查询,我可以看到值 'b' 已插入。
如果我将语句包装在 TRY/CATCH 块中,一切都会按预期工作,并且整个事务操作都会回滚:
BEGIN TRANSACTION
BEGIN TRY
exec sp_executesql N'some nonsense'
insert into testTable values ('b')
COMMIT
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE()
ROLLBACK
END CATCH
SET XACT_ABORT ON 不应该确保在出现问题时回滚整个事务吗?有没有我遗漏的设置?
谢谢
【问题讨论】:
-
看起来这取决于
some nonsense是什么,如果它是编译时错误,它的行为就像你说的那样。如果是运行时错误(例如exec sp_executesql N'SELECT 1/0'),它会按照您的意愿行事。 -
好吧,我不知道这会有所作为。我有一个语法错误,这可以解释。但是,是否有一些文档可以解释它为什么这样做?我仍然希望整个事务能够回滚,即使它是编译时错误。还是 XACT_ABORT 选项只处理运行时错误?
-
我以前不知道这种行为。我不知道这是否是“设计使然”。
-
文档确实说“当 SET XACT_ABORT 为 ON 时,如果 Transact-SQL 语句引发 run-time 错误,则整个事务将终止并回滚。”所以也许从技术上讲,它正在做它应该做的事情。由于错误是编译时错误,尽管是在外部运行的批处理中。
-
@JeroenMostert 你能把这个写在答案中,以便我选择它吗?我认为这描述了我所追求的,这就是发生这种情况的原因。
标签: sql-server transactions sql-server-2014 xact-abort