根据定义,如果其中的任何语句导致错误,则应取消T-SQL事务。但是,我偶然发现事务通过并在其中途发生错误的情况。
示例环境设置:
--test tables:
IF OBJECT_ID('t2', 'U') IS NOT NULL
DROP TABLE t2;
GO
IF OBJECT_ID('t1', '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), (3), (4), (6);
GO
交易测试:
BEGIN TRANSACTION
INSERT INTO t2 VALUES (1);
INSERT INTO t2 VALUES (2); -- Foreign key error will be thrown.
INSERT INTO t2 VALUES (3);
COMMIT TRANSACTION;
这应该是由于外键错误而取消的,但不是:
SELECT * FROM t2;
返回两行的结果-值1和3。
添加SET XACT_ABORT ON
可以完成这项工作,但是当中间出现错误时,整个交易怎么可能停滞不前?
答案 0 :(得分:2)
根据特定的错误,在没有XACT_ABORT ON
的错误之后,T-SQL批处理将继续。我建议在TRY/CATCH
中加上IF @@TRANCOUNT > 0 ROLLBACK;
和CATCH BLOCK
中的XACT_ABORT ON
以确保在查询取消或客户端超时的情况下立即回滚(这可以防止{{1 }}阻止执行):
CATCH