Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 为什么在INSERT INTO失败时自动回滚我的事务?_Sql Server_Tsql_Sql Server 2008_Transactions_Rdbms - Fatal编程技术网

Sql server 为什么在INSERT INTO失败时自动回滚我的事务?

Sql server 为什么在INSERT INTO失败时自动回滚我的事务?,sql-server,tsql,sql-server-2008,transactions,rdbms,Sql Server,Tsql,Sql Server 2008,Transactions,Rdbms,令人惊讶的是,我找不到任何关于这个问题的相关解释或文档 对于这些SQL语句: SELECT 1 AS Test INTO #tmpTest BEGIN TRAN SELECT 1 AS Test INTO #tmpTest ROLLBACK TRAN 当逐个执行时,选择。。。如预期的那样,在第3行中的输入失败,并显示消息- 数据库中已存在名为“tmpTest”的对象 但是,在此之后,第4行中的ROLLBACK语句失败: 回滚事务请求没有相应的开始 交易 即使交易确实从第

令人惊讶的是,我找不到任何关于这个问题的相关解释或文档

对于这些SQL语句:

SELECT 1 AS Test INTO #tmpTest    
BEGIN TRAN    
SELECT 1 AS Test INTO #tmpTest    
ROLLBACK TRAN
当逐个执行时,选择。。。如预期的那样,在第3行中的输入失败,并显示消息-

数据库中已存在名为“tmpTest”的对象

但是,在此之后,第4行中的ROLLBACK语句失败:

回滚事务请求没有相应的开始 交易

即使交易确实从第2行成功开始

我已经看到了,但是这里的答案不适用,因为默认的xact_abort是关闭的。除此之外,这一观点与事实相矛盾

实际解释是什么?

请参阅

在这种情况下,您得到的是一次批量流产,这会导致隐式回滚。该博客是关于SQLServer2000错误处理的,但大部分内容仍然有效

编辑:进一步挖掘并发现了这一点,其中特别提到了尝试创建一个已经存在的表的情况:
根据这篇Microsoft文章:

。。。发生错误,导致交易被分类 作为不可提交的事务。请求无法提交请求 事务或回滚到保存点;它只能要求一个完整的 事务的回滚

我首先运行以下命令:

SELECT 1 AS Test INTO #tmpTest    
SELECT @@TRANCOUNT, XACT_STATE()
BEGIN TRAN    
SELECT @@TRANCOUNT, XACT_STATE()
然后:

CATCH块中的SELECT返回:数据库中已经有一个名为“tmpTest”的对象。@@TRANCOUNT为1,但XACT_状态为-1,因此SSMS中的错误消息状态为:

Msg 3998,级别16,状态1,第1行不可提交事务为 在批次结束时检测到。事务被回滚


下一个SELECT@@TRANCOUNT返回0。

我在SQL 2017上也尝试过同样的方法。有趣。使用SQL Server 2016,我在第二条SELECT语句前后添加了一个SELECT@@TRANCOUNT,然后逐行执行。第一个按预期返回1,然后选择失败,然后第二个@TRANCOUNT返回0。但是,将错误的选择包装在try/catch中,仍然有一个打开的事务进入catch块。有趣的是,我成功地得到了这样一条消息:在批处理结束时检测到Msg 3998,级别16,状态1,第1行未提交事务。事务已回滚。另一个答案比您接受的答案更准确。批量中止是您看到的行为的关键。我猜您是对的@MartinSmith。
BEGIN TRY
    SELECT 1 AS Test INTO #tmpTest    
END TRY
BEGIN CATCH
    SELECT @@ERROR, ERROR_MESSAGE()
    SELECT @@TRANCOUNT, XACT_STATE()
END CATCH