Правильный способ использования транзакции с несколькими вставками или обновлениями

Каков правильный способ проверки на наличие сбоев вставки/обновления и откат этой транзакции, если они есть? Я не думаю, что то, что у меня будет, будет работать, так как мои вставки/обновления - это 3 отдельных оператора, а @@ROWCOUNT будет отражать только последний выполненный оператор.

BEGIN TRANSACTION Script;
GO

INSERT INTO TableA (id) VALUES (1)
INSERT INTO TableB (id) VALUES (1)
UPDATE TableC SET id=1 WHERE id=2
GO

IF (@@ROWCOUNT=3 AND @@ERROR=0)
    BEGIN
    COMMIT
    END
ELSE
    BEGIN
    PRINT 'Error: Rolling back transaction'
    ROLLBACK TRANSACTION Script
    END
GO

Ответ 1

Если вы положите SET XACT_ABORT ON перед началом транзакции, в случае ошибки, откат будет выдаваться автоматически.

SET XACT_ABORT ON

begin transaction

INSERT INTO TableA (id) VALUES (1)
INSERT INTO TableB (id) VALUES (1)
UPDATE TableC SET id=1 WHERE id=2

commit transaction

Если вы хотите выполнить откат самостоятельно, используйте try.. catch block.

begin transaction

begin try

  INSERT INTO TableA (id) VALUES (1)
  INSERT INTO TableB (id) VALUES (1)
  UPDATE TableC SET id=1 WHERE id=2

  commit transaction

end try

begin catch
  raiserror('Message here', 16, 1)
  rollback transaction
end catch

Ответ 2

Я не знаю, к какой версии вы подключились, но с SQL 2005 был try/catch:

begin transaction
begin try
   INSERT INTO TableA (id) VALUES (1)
   INSERT INTO TableB (id) VALUES (1)
   UPDATE TableC SET id=1 WHERE id=2
end try
begin catch
   SELECT
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() AS ErrorState,
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_MESSAGE() AS ErrorMessage;
   while(@@trancount > 0)
   begin
      rollback transaction
   end
end catch
if (@@trancount <> 0)
begin
   commit transaction;
end

Ответ 3

Неудачные вставки будут выбрасываться. "Неудачные" обновления могут быть обнаружены с помощью @@ROWCOUNT.