2012-04-14 5 views
151

Tengo 2 comandos y necesito que ambos se ejecuten correctamente o ninguno de ellos se ejecute. Entonces, creo que necesito una Transacción, pero no sé cómo usarla correctamente.Uso correcto de transacciones en SQL Server 2008

¿Cuál es el problema con el siguiente script?

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 

El comando ejecutado insert pero el comando update tiene un problema. ¿Cómo puedo implementar esto para deshacer ambos comandos si alguno de ellos tiene un error en la ejecución?

Respuesta

350

Añadir un bloque try/catch, si la operación tiene éxito va a confirmar los cambios, si falla la operación de la transacción se revierte:

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

Esta es una respuesta más apropiada. –

+9

Buena respuesta. Tal como está escrito, esto suprimirá el mensaje de error. Agregue 'PRINT ERROR_MESSAGE()' después de la restauración para visualizarlo. – atheaos

+1

¿No debería 'BEGIN TRANSACTION [Tran1]' colocarse dentro de 'TRY'? De todos modos, una pieza de código muy simple y elegante. –

95

Al inicio de procedimiento almacenado se debe poner SET XACT_ABORT ON para instruir Sql Server para retrotraer automáticamente la transacción en caso de error. Si se omite o se establece en OFF, se necesita probar @@ERROR después de cada declaración o utilizar el bloque TRY ... CATCH rollback.

+4

¿Cómo puede ser esta la respuesta aceptada? –

+4

Porque es la [respuesta correcta] (https://msdn.microsoft.com/en-us/library/ms188792.aspx): "Cuando SET XACT_ABORT está desactivado, en algunos casos solo la instrucción de Transact-SQL que el error se retrotrae y la transacción continúa procesándose. Dependiendo de la gravedad del error, toda la transacción puede revertirse incluso cuando SET XACT_ABORT está DESACTIVADO. OFF es la configuración predeterminada. " La pregunta original es por qué ocurre INSERT pero se revierte UPDATE. Incluso con TRY-CATCH, su INSERT se ejecutará primero y se comprometerá. Sin embargo, TRY-CATCH todavía se puede usar por flexibilidad. – 4AM

+1

En otras palabras, su transacción no es atómica a menos que primero configure SET XACT_ABORT. – 4AM

22

enfoque Fácil:

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; 
Cuestiones relacionadas