如果我运行以下内容:
CREATE TABLE t1
(a INT NOT NULL PRIMARY KEY);
CREATE TABLE t2
(a INT NOT NULL REFERENCES t1(a));
INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (3);
INSERT INTO t1 VALUES (4);
INSERT INTO t1 VALUES (6);
GO
Run Code Online (Sandbox Code Playgroud)
然后我运行这个:
SET XACT_ABORT ON;
BEGIN TRANSACTION
INSERT INTO t2 VALUES (1)
INSERT INTO t2 VALUES (2) -- Foreign key error, entire transaction rolled back
INSERT INTO t2 VALUES (3)
COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)
一切都好; 事务被回滚,因为我们在t1中没有值2,因此表t2为空
但是,如果我GO在此事务中间添加一个命令,则事务不会回滚,并且数字3将插入到表t2中.这是代码:
SET XACT_ABORT ON;
BEGIN TRANSACTION
INSERT INTO t2 VALUES (1)
INSERT INTO t2 VALUES (2) -- Foreign key error.
GO --this command breaks the transaction
INSERT INTO t2 VALUES (3)
COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)
我知道这GO不是一个sql语句,而是一个实际上没有发送到SQL服务器的SQL Server Management Studio实用程序命令.
那么,为什么在运行上面的最后一个代码片段(包含GO命令的代码片段)后,我可以看到表t2中的数字3
我使用过SQL Server Management Studio
如果
SET XACT_ABORT是ON,如果Transact-SQL语句引发运行时错误,则终止并回滚整个事务.
在第一批中打开的事务会在出错时自动回滚.
然后SSMS看到有另一批要处理并开火
INSERT INTO t2 VALUES (3)
COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)
当第一个事务现在关闭时,这将启动一个新的自动提交事务.并且最后会出现意外情况,COMMIT TRANSACTION从而引发错误.
您可以更改第二批以检查第一批中的事务是否被毫不客气地回滚.
SET XACT_ABORT ON;
BEGIN TRANSACTION
INSERT INTO t2 VALUES (1)
INSERT INTO t2 VALUES (2) -- Foreign key error.
GO
IF @@TRANCOUNT = 0
BEGIN
RAISERROR('Transaction closed',16,1);
RETURN;
END
INSERT INTO t2 VALUES (3)
COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)
或者您可以打开SQLCMD模式并使用
:on error exit
Run Code Online (Sandbox Code Playgroud)
如果您不想在错误后处理更多批次.