这个事务为什么出错了,但是还是插入成功了?

时间:2021-01-16 04:18:30
create table Table1 (a tinyint)
go
begin tran
  insert table1 values(1)              ----成功
  insert table1 values(1000)           ----这句将报错
commit tran

select * from table1         ------结果是一个失败,一个成功

我以为应该全部回滚的,难道这个错误还没到一定级别?所以没回滚??

12 个解决方案

#1


这是microsoft user group 上的解析。
仔细看看吧。
It's usually up to you to either commit or rollback the transaction.  If you
begin a transaction and there is an error and you still issue the commit why
would you expect otherwise.  Maybe you are used to having SET XACT_ABORT ON.
现翻译如下:
事务的提交或回退往往取决于你,如果你开始一个事务,有错误发生,你仍然提交,为什么希望这样呢。你可能set xact_abort on.

在后面加set xact_abort on上就好了。

#2


SET XACT_ABORT
指定当 Transact-SQL 语句产生运行时错误时,Microsoft® SQL Server™ 是否自动回滚当前事务。

语法
SET XACT_ABORT { ON | OFF }

注释
当 SET XACT_ABORT 为 ON 时,如果 Transact-SQL 语句产生运行时错误,整个事务将终止并回滚。为 OFF 时,只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。编译错误(如语法错误)不受 SET XACT_ABORT 的影响。

对于大多数 OLE DB 提供程序(包括 SQL Server),隐性或显式事务中的数据修改语句必须将 XACT_ABORT 设置为 ON。唯一不需要该选项的情况是提供程序支持嵌套事务时。有关更多信息,请参见分布式查询和分布式事务。 

SET XACT_ABORT 的设置是在执行或运行时设置,而不是在分析时设置。

示例
下例导致在含有其它 Transact-SQL 语句的事务中发生违反外键错误。在第一个语句集中产生错误,但其它语句均成功执行且事务成功提交。在第二个语句集中,SET XACT_ABORT 设置为 ON。这导致语句错误使批处理终止,并使事务回滚。 

CREATE TABLE t1 (a int PRIMARY KEY)
CREATE TABLE t2 (a int REFERENCES t1(a))
GO
INSERT INTO t1 VALUES (1)
INSERT INTO t1 VALUES (3)
INSERT INTO t1 VALUES (4)
INSERT INTO t1 VALUES (6)
GO
SET XACT_ABORT OFF
GO
BEGIN TRAN
INSERT INTO t2 VALUES (1)
INSERT INTO t2 VALUES (2) /* Foreign key error */
INSERT INTO t2 VALUES (3)
COMMIT TRAN
GO

SET XACT_ABORT ON
GO

BEGIN TRAN
INSERT INTO t2 VALUES (4)
INSERT INTO t2 VALUES (5) /* Foreign key error */
INSERT INTO t2 VALUES (6)
COMMIT TRAN
GO

/* Select shows only keys 1 and 3 added. 
   Key 2 insert failed and was rolled back, but
   XACT_ABORT was OFF and rest of transaction
   succeeded.
   Key 5 insert error with XACT_ABORT ON caused
   all of the second transaction to roll back. */

SELECT * 
FROM t2
GO

DROP TABLE t2
DROP TABLE t1
GO

#3


兩種方法:
1: 在事務開始前加上 set xact_abort on
2: 在每條insert 或 update 或delete 語句后面加上
if @@error <> 0  
begin 
 rollback tran 
 return
end

#4


1、
SET IMPLICIT_TRANSACTIONS on 隐性事务模式,也就是自动产生事务,必须显式提交或者取消,OFF的时候每个语句都是一个单独的事务,不必显式提交,除非显式开始事务

〉〉此时也返回@@trancount=1,但我觉得应该返回0,因为系统自动提交,相当于
commit了。

use pubs
go
SET IMPLICIT_TRANSACTIONS ON
select * from authors
select @@trancount
--此时返回@@trancount=1,这还可以理解
ROLLBACK    ----OR COMMIT 完成一次测试

use pubs
go
SET IMPLICIT_TRANSACTIONS OFF
select * from authors
select @@trancount
----这时应该返回0

2、需要理解活动事务的概念

use pubs
go
SET IMPLICIT_TRANSACTIONS ON

UPDATE authors
SET phone ='12345'
WHERE au_id='172-32-1176'

select @@trancount
DBCC OPENTRAN('pubs')



以下是帮助内容:

SET IMPLICIT_TRANSACTIONS
为连接设置隐性事务模式。

语法
SET IMPLICIT_TRANSACTIONS { ON | OFF }

注释
当设置为 ON 时,SET IMPLICIT_TRANSACTIONS 将连接设置为隐性事务模式。当设置为 OFF 时,则使连接返回到自动提交事务模式。

当连接是隐性事务模式且当前不在事务中时,执行下列语句将启动事务:

ALTER TABLE FETCH REVOKE 
CREATE GRANT SELECT 
DELETE INSERT TRUNCATE TABLE 
DROP OPEN UPDATE 


如果连接已经在打开的事务中,则上述语句不启动新事务。

对于因为该设置为 ON 而自动打开的事务,用户必须在该事务结束时将其显式提交或回滚。否则当用户断开连接时,事务及其所包含的所有数据更改将回滚。在事务提交后,执行上述任一语句即可启动新事务。

隐性事务模式将保持有效,直到连接执行 SET IMPLICIT_TRANSACTIONS OFF 语句使连接返回到自动提交模式。在自动提交模式下,如果各个语句成功完成则提交。

在进行连接时,SQL Server ODBC 驱动程序和用于 SQL Server 的 Microsoft OLE DB 提供程序自动将 IMPLICIT_TRANSACTIONS 设置为 OFF。对来自 DB-Library 应用程序的连接,SET IMPLICIT_TRANSACTIONS 默认为 OFF。

当 SET ANSI_DEFAULTS 为 ON 时,将启用 SET IMPLICIT_TRANSACTIONS。

SET IMPLICIT_TRANSACTIONS 的设置是在执行或运行时设置,而不是在分析时设置。


#5


學習

#6


你看看一下内容就明白了:)

编译和运行时错误
在自动提交模式下,有时看起来 SQL Server 好像回滚了整个批处理,而不是仅仅一个 SQL 语句。这种情况只有在遇到的错误是编译错误而不是运行时错误时才会发生。编译错误将阻止 SQL Server 建立执行计划,这样批处理中的任何语句都不会执行。尽管看起来好像是产生错误之前的所有语句都被回滚了,但实际情况是该错误使批处理中的任何语句都没有执行。在此例中,由于编译错误,第三个批处理中的任何 INSERT 语句都没有执行。但看上去好像是前两个 INSERT 语句没有执行便进行了回滚。

USE pubs
GO
CREATE TABLE TestBatch (Cola INT PRIMARY KEY, Colb CHAR(3))
GO
INSERT INTO TestBatch VALUES (1, 'aaa')
INSERT INTO TestBatch VALUES (2, 'bbb')
INSERT INTO TestBatch VALUSE (3, 'ccc')  /* Syntax error */
GO
SELECT * FROM TestBatch   /* Returns no rows */
GO

在下面的示例中,第三个 INSERT 语句产生运行时重复键错误。由于前两个 INSERT 语句成功地执行并且提交,因此它们在运行时错误之后被保留下来。

USE pubs
GO
CREATE TABLE TestBatch (Cola INT PRIMARY KEY, Colb CHAR(3))
GO
INSERT INTO TestBatch VALUES (1, 'aaa')
INSERT INTO TestBatch VALUES (2, 'bbb')
INSERT INTO TestBatch VALUES (1, 'ccc')  /* Duplicate key error */
GO
SELECT * FROM TestBatch   /* Returns rows 1 and 2 */
GO

SQL Server 使用延迟的名称解析,其中对象名直到执行时才被解析。在下面的示例中,前两个 INSERT 语句执行并提交,当第三个 INSERT 语句由于引用了一个并不存在的表而产生运行时错误之后,前两行将仍然保留在 TestBatch 表中。

USE pubs
GO
CREATE TABLE TestBatch (Cola INT PRIMARY KEY, Colb CHAR(3))
GO
INSERT INTO TestBatch VALUES (1, 'aaa')
INSERT INTO TestBatch VALUES (2, 'bbb')
INSERT INTO TestBch VALUES (3, 'ccc')  /* Table name error */
GO
SELECT * FROM TestBatch   /* Returns rows 1 and 2 */
GO

#7


create table Table1 (a tinyint)
go
begin tran
  insert table1 values(1)              ----成功
  if @@Error<>0 goto Lb_Error
  insert table1 values(1000)           ----这句将报错
  if @@Error<>0 goto Lb_Error
commit tran
return 0
Lb_Error:
  Rollback tran
  return 100

#8


SET XACT_ABORT on
go

create table #Table1 (a tinyint)
go
begin tran
  insert #table1 values(1)              ----成功
  insert #table1 values(1000)           ----这句将报错
commit tran
go
select * from #table1 
go
drop table #table1

#9


这里高手真多:)
谢谢大家:)

#10


在看看吧:
格式如下
begin tran
insert table1 values(1)            ----successful  insert
if @@error <> 0
 begin
     rollback transaction
     goto done
 end

insert table1 values(1000)           ----will report error
if @@error <> 0
 begin
     rollback transaction
     goto done
 end

commit tran

#11


需要配置:
SET XACT_ABORT ON

#12


up

#1


这是microsoft user group 上的解析。
仔细看看吧。
It's usually up to you to either commit or rollback the transaction.  If you
begin a transaction and there is an error and you still issue the commit why
would you expect otherwise.  Maybe you are used to having SET XACT_ABORT ON.
现翻译如下:
事务的提交或回退往往取决于你,如果你开始一个事务,有错误发生,你仍然提交,为什么希望这样呢。你可能set xact_abort on.

在后面加set xact_abort on上就好了。

#2


SET XACT_ABORT
指定当 Transact-SQL 语句产生运行时错误时,Microsoft&reg; SQL Server&#8482; 是否自动回滚当前事务。

语法
SET XACT_ABORT { ON | OFF }

注释
当 SET XACT_ABORT 为 ON 时,如果 Transact-SQL 语句产生运行时错误,整个事务将终止并回滚。为 OFF 时,只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。编译错误(如语法错误)不受 SET XACT_ABORT 的影响。

对于大多数 OLE DB 提供程序(包括 SQL Server),隐性或显式事务中的数据修改语句必须将 XACT_ABORT 设置为 ON。唯一不需要该选项的情况是提供程序支持嵌套事务时。有关更多信息,请参见分布式查询和分布式事务。 

SET XACT_ABORT 的设置是在执行或运行时设置,而不是在分析时设置。

示例
下例导致在含有其它 Transact-SQL 语句的事务中发生违反外键错误。在第一个语句集中产生错误,但其它语句均成功执行且事务成功提交。在第二个语句集中,SET XACT_ABORT 设置为 ON。这导致语句错误使批处理终止,并使事务回滚。 

CREATE TABLE t1 (a int PRIMARY KEY)
CREATE TABLE t2 (a int REFERENCES t1(a))
GO
INSERT INTO t1 VALUES (1)
INSERT INTO t1 VALUES (3)
INSERT INTO t1 VALUES (4)
INSERT INTO t1 VALUES (6)
GO
SET XACT_ABORT OFF
GO
BEGIN TRAN
INSERT INTO t2 VALUES (1)
INSERT INTO t2 VALUES (2) /* Foreign key error */
INSERT INTO t2 VALUES (3)
COMMIT TRAN
GO

SET XACT_ABORT ON
GO

BEGIN TRAN
INSERT INTO t2 VALUES (4)
INSERT INTO t2 VALUES (5) /* Foreign key error */
INSERT INTO t2 VALUES (6)
COMMIT TRAN
GO

/* Select shows only keys 1 and 3 added. 
   Key 2 insert failed and was rolled back, but
   XACT_ABORT was OFF and rest of transaction
   succeeded.
   Key 5 insert error with XACT_ABORT ON caused
   all of the second transaction to roll back. */

SELECT * 
FROM t2
GO

DROP TABLE t2
DROP TABLE t1
GO

#3


兩種方法:
1: 在事務開始前加上 set xact_abort on
2: 在每條insert 或 update 或delete 語句后面加上
if @@error <> 0  
begin 
 rollback tran 
 return
end

#4


1、
SET IMPLICIT_TRANSACTIONS on 隐性事务模式,也就是自动产生事务,必须显式提交或者取消,OFF的时候每个语句都是一个单独的事务,不必显式提交,除非显式开始事务

〉〉此时也返回@@trancount=1,但我觉得应该返回0,因为系统自动提交,相当于
commit了。

use pubs
go
SET IMPLICIT_TRANSACTIONS ON
select * from authors
select @@trancount
--此时返回@@trancount=1,这还可以理解
ROLLBACK    ----OR COMMIT 完成一次测试

use pubs
go
SET IMPLICIT_TRANSACTIONS OFF
select * from authors
select @@trancount
----这时应该返回0

2、需要理解活动事务的概念

use pubs
go
SET IMPLICIT_TRANSACTIONS ON

UPDATE authors
SET phone ='12345'
WHERE au_id='172-32-1176'

select @@trancount
DBCC OPENTRAN('pubs')



以下是帮助内容:

SET IMPLICIT_TRANSACTIONS
为连接设置隐性事务模式。

语法
SET IMPLICIT_TRANSACTIONS { ON | OFF }

注释
当设置为 ON 时,SET IMPLICIT_TRANSACTIONS 将连接设置为隐性事务模式。当设置为 OFF 时,则使连接返回到自动提交事务模式。

当连接是隐性事务模式且当前不在事务中时,执行下列语句将启动事务:

ALTER TABLE FETCH REVOKE 
CREATE GRANT SELECT 
DELETE INSERT TRUNCATE TABLE 
DROP OPEN UPDATE 


如果连接已经在打开的事务中,则上述语句不启动新事务。

对于因为该设置为 ON 而自动打开的事务,用户必须在该事务结束时将其显式提交或回滚。否则当用户断开连接时,事务及其所包含的所有数据更改将回滚。在事务提交后,执行上述任一语句即可启动新事务。

隐性事务模式将保持有效,直到连接执行 SET IMPLICIT_TRANSACTIONS OFF 语句使连接返回到自动提交模式。在自动提交模式下,如果各个语句成功完成则提交。

在进行连接时,SQL Server ODBC 驱动程序和用于 SQL Server 的 Microsoft OLE DB 提供程序自动将 IMPLICIT_TRANSACTIONS 设置为 OFF。对来自 DB-Library 应用程序的连接,SET IMPLICIT_TRANSACTIONS 默认为 OFF。

当 SET ANSI_DEFAULTS 为 ON 时,将启用 SET IMPLICIT_TRANSACTIONS。

SET IMPLICIT_TRANSACTIONS 的设置是在执行或运行时设置,而不是在分析时设置。


#5


學習

#6


你看看一下内容就明白了:)

编译和运行时错误
在自动提交模式下,有时看起来 SQL Server 好像回滚了整个批处理,而不是仅仅一个 SQL 语句。这种情况只有在遇到的错误是编译错误而不是运行时错误时才会发生。编译错误将阻止 SQL Server 建立执行计划,这样批处理中的任何语句都不会执行。尽管看起来好像是产生错误之前的所有语句都被回滚了,但实际情况是该错误使批处理中的任何语句都没有执行。在此例中,由于编译错误,第三个批处理中的任何 INSERT 语句都没有执行。但看上去好像是前两个 INSERT 语句没有执行便进行了回滚。

USE pubs
GO
CREATE TABLE TestBatch (Cola INT PRIMARY KEY, Colb CHAR(3))
GO
INSERT INTO TestBatch VALUES (1, 'aaa')
INSERT INTO TestBatch VALUES (2, 'bbb')
INSERT INTO TestBatch VALUSE (3, 'ccc')  /* Syntax error */
GO
SELECT * FROM TestBatch   /* Returns no rows */
GO

在下面的示例中,第三个 INSERT 语句产生运行时重复键错误。由于前两个 INSERT 语句成功地执行并且提交,因此它们在运行时错误之后被保留下来。

USE pubs
GO
CREATE TABLE TestBatch (Cola INT PRIMARY KEY, Colb CHAR(3))
GO
INSERT INTO TestBatch VALUES (1, 'aaa')
INSERT INTO TestBatch VALUES (2, 'bbb')
INSERT INTO TestBatch VALUES (1, 'ccc')  /* Duplicate key error */
GO
SELECT * FROM TestBatch   /* Returns rows 1 and 2 */
GO

SQL Server 使用延迟的名称解析,其中对象名直到执行时才被解析。在下面的示例中,前两个 INSERT 语句执行并提交,当第三个 INSERT 语句由于引用了一个并不存在的表而产生运行时错误之后,前两行将仍然保留在 TestBatch 表中。

USE pubs
GO
CREATE TABLE TestBatch (Cola INT PRIMARY KEY, Colb CHAR(3))
GO
INSERT INTO TestBatch VALUES (1, 'aaa')
INSERT INTO TestBatch VALUES (2, 'bbb')
INSERT INTO TestBch VALUES (3, 'ccc')  /* Table name error */
GO
SELECT * FROM TestBatch   /* Returns rows 1 and 2 */
GO

#7


create table Table1 (a tinyint)
go
begin tran
  insert table1 values(1)              ----成功
  if @@Error<>0 goto Lb_Error
  insert table1 values(1000)           ----这句将报错
  if @@Error<>0 goto Lb_Error
commit tran
return 0
Lb_Error:
  Rollback tran
  return 100

#8


SET XACT_ABORT on
go

create table #Table1 (a tinyint)
go
begin tran
  insert #table1 values(1)              ----成功
  insert #table1 values(1000)           ----这句将报错
commit tran
go
select * from #table1 
go
drop table #table1

#9


这里高手真多:)
谢谢大家:)

#10


在看看吧:
格式如下
begin tran
insert table1 values(1)            ----successful  insert
if @@error <> 0
 begin
     rollback transaction
     goto done
 end

insert table1 values(1000)           ----will report error
if @@error <> 0
 begin
     rollback transaction
     goto done
 end

commit tran

#11


需要配置:
SET XACT_ABORT ON

#12


up