令人惊讶的是,我找不到与此问题有关的任何解释或文档。
对于这些SQL语句:
SELECT 1 AS Test INTO #tmpTest
BEGIN TRAN
SELECT 1 AS Test INTO #tmpTest
ROLLBACK TRAN
一一执行时,第3行的SELECT ... INTO
会按预期失败,并显示消息-
数据库中已经有一个名为“ #tmpTest”的对象。
但是,此后,第4行中的ROLLBACK
语句失败:
ROLLBACK TRANSACTION请求没有相应的BEGIN 交易。
即使从第2行成功完成了交易 BEGIN
,
我见过SQL Server - transactions roll back on error?,但这里的答案并不适用,因为默认的xact_abort
是off
。 此外,answer from Quassnoi与answer by Raj More相矛盾。
实际解释是什么?
答案 0 :(得分:3)
请参阅http://www.sommarskog.se/error-handling-I.html
在这种情况下,您得到的是批量中止,这将导致隐式回滚。该博客是有关SQL Server 2000错误处理的,但其中大部分仍然有效。
编辑:多进行一些挖掘,发现这一点专门提到了尝试创建一个已经存在的表的情况: http://www.sommarskog.se/error_handling/Part2.html#BatchTranAbort
答案 1 :(得分:2)
此Microsoft文章:XACT_STATE (Transact-SQL)
(...)发生错误,导致交易被分类 作为不可承诺的交易。该请求无法提交 交易或回滚到保存点;它只能要求完整 交易回滚。
我先运行这个:
SELECT 1 AS Test INTO #tmpTest
SELECT @@TRANCOUNT, XACT_STATE()
BEGIN TRAN
SELECT @@TRANCOUNT, XACT_STATE()
然后:
BEGIN TRY
SELECT 1 AS Test INTO #tmpTest
END TRY
BEGIN CATCH
SELECT @@ERROR, ERROR_MESSAGE()
SELECT @@TRANCOUNT, XACT_STATE()
END CATCH
在SELECT
块中的CATCH
返回:“ 数据库中已经有一个名为'#tmpTest'的对象。”,@@TRANCOUNT
是{ {1}},但是1
是XACT_STATE
,因此SSMS中的错误消息指出:
消息3998,第16级,状态1,第1行是不可提交的交易, 在批次结束时检测到。交易被回滚。
下一个-1
返回SELECT @@TRANCOUNT
。