Частичная фиксация SQL Server в транзакции

#sql-server #sqltransaction

#sql-сервер #sqltransaction

Вопрос:

У меня есть транзакция и две таблицы, в которые я вставляю некоторые данные, могу ли я выполнить частичную фиксацию в SQL Server

 BEGIN TRANSACTION tran1
  BEGIN  TRY
    --Insert into Table1
    --Insert into Table2
COMMIT TRANSACTION  tran1                           
  END TRY
BEGIN CATCH
   ROLLBACK TRANSACTION tran1 
END CATCH
  

Приведенный выше код откатит данные обеих таблиц, есть ли способ, которым мы можем зафиксировать таблицу 1, если в вставке таблицы 1 нет ошибки, но откат таблицы 2, если произошла какая-либо ошибка.

Ответ №1:

Ответ — да, хотя транзакции действительно являются атомарными, вы могли бы использовать точку сохранения. Итак, в вашем случае код может выглядеть следующим образом (непроверенный):

 BEGIN  TRY
    BEGIN TRANSACTION
    --Insert into Table1

    -- savepoint
    SAVE TRANSACTION tran1

    --Insert into Table2

    -- commit the whole transaction
    COMMIT TRANSACTION
END TRY

BEGIN CATCH
    -- rollback to savepoint
    IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION tran1 
END CATCH
  

Возможно, вам придется изменить порядок вставки.

Ответ №2:

Нет, ты не можешь. Транзакция является атомарной. То есть все шаги выполняются как один, фиксируются вместе или откатываются. Если вы помещаете обе вставки в одну транзакцию, вы не сможете зафиксировать их в одной таблице. Вы можете использовать различные транзакции, если это возможно.

Комментарии:

1. можете ли вы взглянуть на приведенный выше ответ, видите ли вы какую-либо проблему с вышеуказанным подходом

2. На самом деле выглядит нормально. Эта точка сохранения является функцией MSSQL. В этом случае это почти то же самое, что иметь 2 транзакции, за исключением того, что при первом сбое 2-я не будет работать

3. Чего вы пытаетесь достичь здесь?

4. Нет, я просто изучаю, существует ли эта функция в MSSQL или не более того, в любом случае спасибо, что помогли мне

5. NP, еще один метод, о котором я могу подумать, заключается в том, чтобы поместить try catch внутри транзакции. Таким образом, он попробует обе таблицы