2012-04-24 5 views
10

¿Cuál es la forma correcta de probar las fallas de inserción/actualización y revertir esta transacción si hay alguna? No creo que lo que tengo funcione, ya que mis inserciones/actualizaciones son 3 declaraciones separadas y @@ ROWCOUNT solo reflejará la última instrucción ejecutada.Forma correcta de usar una transacción en varias inserciones o actualizaciones

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 

Respuesta

33

Si pone SET XACT_ABORT en ON antes de iniciar la transacción, in case of an error, rollback will be issued automatically.

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 

Si quiere hacer rollback usted mismo, use 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 
+0

Esto me limita a imprimir un mensaje de error, ¿verdad? –

+0

@JoePhilllips, por favor revisa mi respuesta actualizada. –

+1

¿El atributo SET XACT_ABORT ON generará un mensaje de error cuando la transacción retroceda? – Raza

0

Inserciones fallidas tirarán. Las actualizaciones "fallidas" se pueden detectar usando @@ ROWCOUNT.

2

No sé qué versión estás en, pero ha habido try/catch desde SQL 2005:

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