Ответ 1
Вы можете поместить set xact_abort on
перед транзакцией, чтобы убедиться, что sql откатывается автоматически в случае ошибки.
У нас есть клиентское приложение, которое запускает SQL на SQL Server 2005, например:
BEGIN TRAN;
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
COMMIT TRAN;
Он отправляется одной длинной строковой командой.
Если одна из вложений не работает или какая-либо часть команды выходит из строя, SQL Server откатывает транзакцию? Если он не откат, мне нужно отправить вторую команду для ее возврата?
Я могу указать особенности api и языка, который я использую, но я бы подумал, что SQL Server должен ответить одинаково для любого языка.
Вы можете поместить set xact_abort on
перед транзакцией, чтобы убедиться, что sql откатывается автоматически в случае ошибки.
Вы правы в том, что вся транзакция будет отменена. Вы должны отправить команду для ее возврата.
Вы можете обернуть это в блок TRY CATCH
следующим образом
BEGIN TRY
BEGIN TRANSACTION
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
COMMIT TRAN -- Transaction Success!
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRAN --RollBack in case of Error
-- you can Raise ERROR with RAISEERROR() Statement including the details of the exception
RAISERROR(ERROR_MESSAGE(), ERROR_SEVERITY(), 1)
END CATCH
Здесь код с получением сообщения об ошибке, работающего с MSSQL Server 2016:
BEGIN TRY
BEGIN TRANSACTION
-- Do your stuff that might fail here
COMMIT
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRAN
DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE()
DECLARE @ErrorSeverity INT = ERROR_SEVERITY()
DECLARE @ErrorState INT = ERROR_STATE()
-- Use RAISERROR inside the CATCH block to return error
-- information about the original error that caused
-- execution to jump to the CATCH block.
RAISERROR (@ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.
);
END CATCH
Из статьи MDSN, Управление транзакциями (движок базы данных).
Если в пакете возникает ошибка инструкции времени выполнения (например, нарушение ограничения), поведение по умолчанию в Database Engine сводится к откату только инструкции, которая породила ошибку. Вы можете изменить это поведение, используя инструкцию SET XACT_ABORT. После выполнения SET XACT_ABORT ON любая ошибка выполнения во время выполнения вызывает автоматический откат текущей транзакции. SET XACT_ABORT не влияет на ошибки компиляции, такие как синтаксические ошибки. Для получения дополнительной информации см. SET XACT_ABORT (Transact-SQL).
В вашем случае он откатится от полной транзакции, если какая-либо из вставок не работает.
Если одна из вложений не работает или какая-либо часть команды выходит из строя, SQL-сервер откатывает транзакцию?
Нет, это не так.
Если он не откат, мне нужно отправить вторую команду для ее возврата?
Конечно, вы должны выдать ROLLBACK
вместо COMMIT
.
Если вы хотите решить, следует ли совершать или откатывать транзакцию, вы должны удалить предложение COMMIT
из инструкции, проверить результаты вставки и затем выдать либо COMMIT
, либо ROLLBACK
в зависимости от результатов проверки.