Search code examples
sql-servert-sqltransactions

Why does SQL Server transaction continue when error has occured?


I assumed an error will abort the transaction, but it does not. Why is table t2 created in code below?

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

After running this, the table t2 exists. Here is the output:

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

Msg 2714, Level 16, State 6, Line 1
There is already an object named 't1' in the database.

Msg 3902, Level 16, State 1, Line 2
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

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

Solution

  • You should remove the GO statements in order to make the whole transaction to be rollback:

    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