为什么SQL Server事务会在发生错误时继续?

时间:2017-11-06 10:03:02

标签: sql-server tsql transactions

我假设错误将中止事务,但事实并非如此。为什么在下面的代码中创建表t2?

IF OBJECT_ID('dbo.t1', 'U') IS NOT NULL 
    DROP TABLE dbo.t1

IF OBJECT_ID('dbo.t2', 'U') IS NOT NULL 
    DROP TABLE dbo.t2
GO

SELECT 
    OBJECT_ID(N't1', N'U') AS t1_Exists, 
    OBJECT_ID(N't2', N'U') AS t2_Exists
GO

BEGIN TRANSACTION 

CREATE TABLE t1 (id INT)
GO
CREATE TABLE t1 (id INT)--Causes an error, since t1 already exists
GO
CREATE TABLE t2 (id INT)
GO

COMMIT TRANSACTION 
GO

SELECT 
    OBJECT_ID(N't1', N'U') AS t1_Exists, 
    OBJECT_ID(N't2', N'U') AS t2_Exists

运行此表后,表t2存在。这是输出:

t1_Exists   t2_Exists
----------- -----------
NULL        NULL
  

Msg 2714,Level 16,State 6,Line 1
  数据库中已经有一个名为“t1”的对象。

     

Msg 3902,Level 16,State 1,Line 2
  COMMIT TRANSACTION请求没有相应的BEGIN TRANSACTION。

t1_Exists   t2_Exists
----------- -----------
NULL        370984223

2 个答案:

答案 0 :(得分:2)

您应该删除GO语句,以使整个事务回滚:

IF OBJECT_ID('dbo.t1', 'U') IS NOT NULL 
DROP TABLE dbo.t1
IF OBJECT_ID('dbo.t2', 'U') IS NOT NULL 
DROP TABLE dbo.t2
GO

SELECT OBJECT_ID(N't1', N'U') AS t1_Exists, OBJECT_ID(N't2', N'U') AS t2_Exists
GO



BEGIN TRANSACTION 

CREATE TABLE t1 (id INT)


CREATE TABLE t1 (id INT)--Causes an error, since t1 already exists


CREATE TABLE t2 (id INT)

COMMIT TRANSACTION 



GO

SELECT OBJECT_ID(N't1', N'U') AS t1_Exists, OBJECT_ID(N't2', N'U') AS t2_Exist

答案 1 :(得分:0)

当您在代码中放入“ Go ”语句时,每个Go之间的每个语句都被视为批处理,即使它们位于同一文件中也会单独执行。因此,为了避免这种情况,您应该删除Begin和Commit Transaction之间的所有go语句。在你提交之前。确保会话中是否存在活动事务以使其更安全。喜欢这个

IF OBJECT_ID('dbo.t1', 'U') IS NOT NULL 
DROP TABLE dbo.t1
IF OBJECT_ID('dbo.t2', 'U') IS NOT NULL 
DROP TABLE dbo.t2
GO

SELECT OBJECT_ID(N't1', N'U') AS t1_Exists, OBJECT_ID(N't2', N'U') AS t2_Exists
GO



BEGIN TRANSACTION 

CREATE TABLE t1 (id INT)


CREATE TABLE t1 (id INT)--Causes an error, since t1 already exists


CREATE TABLE t2 (id INT)

IF @@TRANCOUNT>0    
COMMIT TRANSACTION 



GO

SELECT OBJECT_ID(N't1', N'U') AS t1_Exists, OBJECT_ID(N't2', N'U') AS t2_Exist