2012-04-14 4 views
151

У меня есть 2 команды и они должны выполняться правильно или ни один из них не выполняется. Так что я думаю, что мне нужна транзакция, но я не знаю, как правильно ее использовать.Правильное использование транзакций в SQL Server 2008

В чем проблема со следующим скриптом?

BEGIN TRANSACTION [Tran1] 

INSERT INTO [Test].[dbo].[T1] 
    ([Title], [AVG]) 
VALUES ('Tidd130', 130), ('Tidd230', 230) 

UPDATE [Test].[dbo].[T1] 
    SET [Title] = N'az2' ,[AVG] = 1 
    WHERE [dbo].[T1].[Title] = N'az' 

COMMIT TRANSACTION [Tran1] 
GO 

Команда insert выполняется, но команда update имеет проблему. Как я могу реализовать это для отката обеих команд, если у кого-либо из них есть ошибка при выполнении?

ответ

350

Добавить попробовать/поймать блок, если сделка успешно она будет фиксировать изменения, если сделка не может транзакция откатывается:

BEGIN TRANSACTION [Tran1] 

BEGIN TRY 

INSERT INTO [Test].[dbo].[T1] 
    ([Title], [AVG]) 
VALUES ('Tidd130', 130), ('Tidd230', 230) 

UPDATE [Test].[dbo].[T1] 
    SET [Title] = N'az2' ,[AVG] = 1 
WHERE [dbo].[T1].[Title] = N'az' 


COMMIT TRANSACTION [Tran1] 

END TRY 
BEGIN CATCH 
    ROLLBACK TRANSACTION [Tran1] 
END CATCH 

GO 
+13

Это более правильный ответ. –

+9

Хороший ответ. Как написано, это приведет к подавлению сообщения об ошибке. Добавьте «PRINT ERROR_MESSAGE()» после откат, чтобы отобразить его. – atheaos

+1

Не следует ли «НАЧАТЬ ПЕРЕВОД» [Tran1] 'размещаться внутри' TRY'? Во всяком случае - очень простой и элегантный кусок кода. –

95

В начале хранимой процедуры следует положить SET XACT_ABORT ON проинструктировать Sql Server для автоматической откат транзакции в случае ошибки. Если оммитирован или установлен на ВЫКЛ, необходимо выполнить проверку @@ERROR после каждого утверждения или использовать блок TRY ... CATCH rollback.

+4

Как это может быть принятым ответом? –

+4

Потому что это [правильный ответ] (https://msdn.microsoft.com/en-us/library/ms188792.aspx): «Когда SET XACT_ABORT выключен, в некоторых случаях только оператор Transact-SQL, который поднятая ошибка откатывается назад, и транзакция продолжает обработку. В зависимости от серьезности ошибки вся транзакция может быть отброшена даже тогда, когда SET XACT_ABORT выключен. OFF является настройкой по умолчанию. " Исходный вопрос - почему INSERT происходит, но UPDATE откат. Даже с TRY-CATCH ваш INSERT будет работать первым и будет выполнен. Однако TRY-CATCH все еще можно использовать для гибкости. – 4AM

+1

Другими словами, ваша транзакция не является атомной, если вы сначала не установите XACT_ABORT ON. – 4AM

22

Легкий подход:

CREATE TABLE T 
(
    C [nvarchar](100) NOT NULL UNIQUE, 
); 

SET XACT_ABORT ON -- Turns on rollback if T-SQL statement raises a run-time error. 
SELECT * FROM T; -- Check before. 
BEGIN TRAN 
    INSERT INTO T VALUES ('A'); 
    INSERT INTO T VALUES ('B'); 
    INSERT INTO T VALUES ('B'); 
    INSERT INTO T VALUES ('C'); 
COMMIT TRAN 
SELECT * FROM T; -- Check after. 
DELETE T; 
Смежные вопросы