Ні SAVE TRANSACTION
. Я ніколи не знаходив випадку для цього. Я знаю, що деякі люди вважають за краще це, але в усьому, що я коли-небудь робив у будь-якому місці, в якому я працював, поняття помилки, що виникає на будь-якому з вкладених рівнів, означало, що будь-яка робота, яка вже була зроблена, недійсна. Використовуючи, SAVE TRANSACTION
ви повертаєтесь до стану лише перед тим, як викликати цю Збережену процедуру, залишаючи існуючий процес як інакше дійсний.
Якщо ви хочете отримати докладніші відомості SAVE TRANSACTION
, перегляньте інформацію у цій відповіді:
Як відкати, коли з однієї збереженої процедури запускаються 3 збережені процедури
Іншим питанням SAVE TRANSACTION
є нюанс його поведінки, як зазначено на сторінці MSDN для ЗБЕРЕГО ТРАНЗАКЦІЇ (акцент додано):
Повторювані імена точок збереження дозволено в транзакції, але оператор ROLLBACK TRANSACTION, який вказує ім'я точки збереження, поверне транзакцію лише до останньої SAVE TRANSACTION, використовуючи це ім'я.
Це означає, що вам потрібно бути дуже обережним, щоб кожній точці збереження у кожній збереженій процедурі дати ім'я, яке є унікальним для всіх точок збереження у всіх збережених процедурах. Наступні приклади ілюструють цей момент.
Цей перший приклад показує, що відбувається при повторному використанні імені Save Point; повертається лише нижня точка збереження.
IF (OBJECT_ID(N'tempdb..#SaveTranTestA') IS NOT NULL)
BEGIN
DROP TABLE #SaveTranTestA;
END;
CREATE TABLE #SaveTranTestA (SomeVal INT NOT NULL);
BEGIN TRAN; -- start level 1
SAVE TRANSACTION MySavePoint;
SELECT @@TRANCOUNT AS [TranCount]; -- 1
INSERT INTO #SaveTranTestA (SomeVal) VALUES (100);
BEGIN TRAN; -- start level 2
SAVE TRANSACTION MySavePoint;
SELECT @@TRANCOUNT AS [TranCount]; -- 2
INSERT INTO #SaveTranTestA (SomeVal) VALUES (200);
COMMIT; -- exit level 2
SELECT @@TRANCOUNT AS [TranCount]; -- 1
SELECT * FROM #SaveTranTestA;
-- 100
-- 200
ROLLBACK TRANSACTION MySavePoint; -- error occurred; undo actions up to this point
SELECT @@TRANCOUNT AS [TranCount]; -- 1
SELECT * FROM #SaveTranTestA;
-- 100
COMMIT; -- exit level 1
SELECT @@TRANCOUNT AS [TranCount]; -- 0
SELECT * FROM #SaveTranTestA;
-- 100
Цей другий приклад показує, що відбувається, коли ви використовуєте унікальні імена Save Point; бажану точку збереження рівня відкочують назад.
IF (OBJECT_ID(N'tempdb..#SaveTranTestB') IS NOT NULL)
BEGIN
DROP TABLE #SaveTranTestB;
END;
CREATE TABLE #SaveTranTestB (SomeVal INT NOT NULL);
BEGIN TRAN; -- start level 1
SAVE TRANSACTION MySavePointUno;
SELECT @@TRANCOUNT AS [TranCount]; -- 1
INSERT INTO #SaveTranTestB (SomeVal) VALUES (100);
BEGIN TRAN; -- start level 2
SAVE TRANSACTION MySavePointDos;
SELECT @@TRANCOUNT AS [TranCount]; -- 2
INSERT INTO #SaveTranTestB (SomeVal) VALUES (200);
COMMIT; -- exit level 2
SELECT @@TRANCOUNT AS [TranCount]; -- 1
SELECT * FROM #SaveTranTestB;
-- 100
-- 200
ROLLBACK TRANSACTION MySavePointUno; --error occurred; undo actions up to this point
SELECT @@TRANCOUNT AS [TranCount]; -- 1
SELECT * FROM #SaveTranTestB;
-- <no rows>
COMMIT; -- exit level 1
SELECT @@TRANCOUNT AS [TranCount]; -- 0
SELECT * FROM #SaveTranTestB;
-- <no rows>