SQL Server automatically rolls back
the current transaction when a Transact-SQL statement raises a run-time error.
When SET XACT_ABORT is
ON, if a Transact-SQL statement raises a run-time error, the entire transaction
is terminated and rolled back.
When SET XACT_ABORT is
OFF, in some cases only the Transact-SQL statement that raised the error is
rolled back and the transaction continues processing.
XACT_ABORT must be set ON for data modification
statements in an implicit or explicit transaction against most OLE DB
providers, including SQL Server. The setting of SET
XACT_ABORT is set at execute or run time and not at parse time.
Remember: Compile
errors, such as syntax errors, are not affected by SET XACT_ABORT.
The following code
example causes a foreign key violation error in a transaction that has other
Transact-SQL statements. In the first set of statements, the error is
generated, but the other statements execute successfully and the transaction is
successfully committed. In the second set of statements, SET XACT_ABORT is
set to ON. This causes the statement error to terminate
the batch and the transaction is rolled back.
IF OBJECT_ID(N't2', N'U') IS NOT NULL
DROP TABLE t2;
GO
IF OBJECT_ID(N't1', N'U') IS NOT NULL
DROP TABLE t1;
GO
CREATE TABLE t1
(a INT NOT NULL PRIMARY KEY);
CREATE TABLE t2
(a INT NOT NULL 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 TRANSACTION;
INSERT INTO t2 VALUES (1);
INSERT INTO t2 VALUES (2); -- Foreign key error.
INSERT INTO t2 VALUES (3);
COMMIT TRANSACTION;
GO
SET XACT_ABORT ON;
GO
BEGIN TRANSACTION;
INSERT INTO t2 VALUES (4);
INSERT INTO t2 VALUES (5); -- Foreign key error.
INSERT INTO t2 VALUES (6);
COMMIT TRANSACTION;
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