--Drop Table Tab1
Begin Transaction TR1;
Save Transaction TR1;
Create Table Tab1(f1 decimal(10,0));
Begin Transaction TR2
Save Transaction TR2
insert into Tab1 values(1);
Begin Transaction TR3;
Save Transaction TR3;
insert into Tab1 values(2);
Begin Try
insert into Tab1 values('OK');
Commit Transaction TR3;
END TRY
BEGIN Catch
print 'catch'
RollBack Transaction TR3;
End Catch
insert into Tab1 values(3);
Commit Transaction TR2
insert into Tab1 values(4);
Commit Transaction TR1;
--Commit Transaction;
select * from Tab1;
Drop Table Tab1
Select @@TRANCount
错误发生:
Msg 3931,Level 16,State 1,Line 17 当前事务无法提交,也无法回滚到保存点。回滚整个交易。
如何处理。
答案 0 :(得分:3)
当引发某些类型的错误时,您无法回滚到保存点。请参阅Martin Smith's的Rollback transaction to savepoint on failing ALTER TABLE … ADD CONSTRAINT回复。您检测到这种情况的方法是测试Xact_state()
。
但是,您的问题有些不同,因为您还尝试使用嵌套事务。嵌套事务在SQL中并不像我们期望的那样真正起作用。
例如,Cannot roll back TR2. No transaction or savepoint of that name was found.
BEGIN TRANSACTION TR1; BEGIN TRANSACTION TR2 ROLLBACK TRANSACTION TR2 COMMIT Transaction TR1
SQL Server数据库引擎
ROLLBACK TRANSACTION语句的transaction_name参数引用一组命名嵌套事务的内部事务是不合法的。 transaction_name只能引用最外层事务的事务名称
Paul S. Randal在A SQL Server DBA myth a day: (26/30) nested transactions are real
中进一步探讨了这一点您可以做的最好的事情是使用保存点,并检查捕获中的Xact_state以及最后。
BEGIN TRANSACTION tr1;
SAVE TRANSACTION tr2;
CREATE TABLE tab1
(
f1 DECIMAL(10, 0)
);
SAVE TRANSACTION tr3
INSERT INTO tab1
VALUES (1);
SAVE TRANSACTION tr4;
INSERT INTO tab1
VALUES (2);
BEGIN try
-- change the order of the follwoing two lines around to see the difference
INSERT INTO tab1 VALUES (1 / 0); --Results in a rollback to savepoint
INSERT INTO tab1 VALUES ('OK'); --Results in a complete rollback
COMMIT TRANSACTION tr4;
END try
BEGIN catch
IF Xact_state() = -1
BEGIN
PRINT 'rollback transaction no other work can be done'
ROLLBACK TRANSACTION;
END
ELSE
BEGIN
PRINT 'rollback to savepoint'
ROLLBACK TRANSACTION tr4
END
END catch
IF Xact_state() > 0
BEGIN
INSERT INTO tab1
VALUES (3);
INSERT INTO tab1
VALUES (4);
COMMIT TRANSACTION tr1;
SELECT *
FROM tab1;
DROP TABLE tab1
END