Я использую транзакции впервые, поэтому я могу задаться глупым вопросом.Каков правильный способ использования нескольких точек сохранения
Я хочу, чтобы вставить данные в 3 таблицы:
Table1(p1,p2,p3)
Table2(q1,q2)
Table3(t3,fk1,fk2)
Например, если что-то пойдет не так, и данные не могут быть вставлены в Table2
, данные Table1
не будут потеряны, и Table3
остается неизменной (и наоборот) ,
Я уже пробовал две версии, но ни один из них не удовлетворяет.
Версия 1:
CREATE PROCEDURE InsertInto(@p1,@p2,@p3,@q1,@q2,@t3))
AS BEGIN
BEGIN TRAN
SET XACT_ABORT OFF
SAVE TRANSACTION point1
BEGIN TRY
DECLARE @fk1 INT
INSERT INTO Table1 VALUES (@p1,@p2,@p3)
SELECT @fk1 = Table1.Id FROM Table1 WHERE Table1.p1 = @p1
SAVE TRANSACTION point2
BEGIN TRY
DECLARE @fk2 INT
INSERT INTO Table2 VALUES (@q1,@q2)
SELECT @fk2 = Table2.Id FROM Table2 WHERE Table2.q1 = @q1
SAVE TRANSACTION point3
BEGIN TRY
INSERT INTO Table3 VALUES (@t3, @fk1, @fk2)
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point3
COMMIT TRAN
END CATCH
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point2
COMMIT TRAN
END CATCH
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point1
COMMIT TRAN
END CATCH
END
Но если данные не могут быть вставлены в Table1
, то возможные данные для Table2
теряется, и я не хочу терять ничего. Итак, я попытался разбить его.
Версия 2:
CREATE PROCEDURE InsertInto(@p1,@p2,@p3,@q1,@q2,@t3)
AS
BEGIN
BEGIN TRAN
SET XACT_ABORT OFF
SAVE TRANSACTION point1
BEGIN TRY
DECLARE @fk1 INT
INSERT INTO Table1 VALUES (@p1,@p2,@p3)
SELECT @fk1 = Table1.Id FROM Table1 WHERE Table1.p1 = @p1
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point1
COMMIT TRAN
END CATCH
SAVE TRANSACTION point2
BEGIN TRY
DECLARE @fk2 INT
INSERT INTO Table2 VALUES (@q1,@q2)
SELECT @fk2 = Table2.Id FROM Table2 WHERE Table2.q1 = @q1
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point2
COMMIT TRAN
END CATCH
SAVE TRANSACTION point3
BEGIN TRY
INSERT INTO Table3 VALUES (@t3,@fk1,@fk2)
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point3
COMMIT TRAN
END CATCH
END
Но если Вставить в терпит неудачу Table2, я получаю это:
(1 строка (ы) пострадавших)
(0 строк (ы) пострадавших)
Msg 628, уровень 16, состояние 0, процедура InsertInto, строка 26 (второй BEGIN CATCH)
Невозможно выдавать SAVE TRANSACTION, когда нет активных транзакций на.
Как я могу это сделать правильно?
Кажется, что вы не должны использовать точки сохранения вообще здесь, а просто фиксируете после каждого шага, а затем начинаете новую транзакцию. Можете ли вы объяснить, почему вы используете точки сохранения? Возможно, некоторое использование вашего кода просто непонятно из вопроса. – hvd
Я хочу узнать, как использовать точки сохранения, чтобы я не терял данные во время транзакции. – user1012732