Por defecto, las transacciones, la mayoría de las veces, no se revierten / cancelan automáticamente cuando se produce un error. Por lo general, esto no es un problema siempre y cuando tenga un manejo adecuado de los errores y se llame a ROLLBACKsí mismo. Sin embargo, a veces las cosas se complican, como en el caso de errores de aborto por lotes, o cuando se usa OPENQUERY(o servidores vinculados en general) y se produce un error en el sistema remoto. Si bien la mayoría de los errores se pueden atrapar usando TRY...CATCH, hay dos que no se pueden atrapar de esa manera (sin embargo, no puedo recordar cuáles en este momento, investigar). En estos casos, debe usar SET XACT_ABORT ONpara deshacer correctamente la transacción.
SET XACT_ABORT ON hace que SQL Server revierta inmediatamente cualquier transacción (si hay una activa) y cancela el lote si se produce algún error. Esta configuración existía antes de SQL Server 2005, que introdujo la TRY...CATCHconstrucción. En su mayor parte, TRY...CATCHmaneja la mayoría de las situaciones y, por lo tanto, en su mayoría obsoletos la necesidad de XACT_ABORT ON. Sin embargo, cuando lo use OPENQUERY(y posiblemente otro escenario que no puedo recordar en este momento), aún tendrá que usarlo SET XACT_ABORT ON;.
Siempre debe tener un manejo adecuado de los errores, especialmente al usar Transacciones. La TRY...CATCHconstrucción, introducida en SQL Server 2005, proporciona un medio para manejar casi todas las situaciones, una mejora bienvenida sobre las pruebas para @@ERRORdespués de cada declaración, que no ayudó mucho con los errores de aborto por lotes.
TRY...CATCHintrodujo un nuevo "estado", sin embargo. Cuando no se utiliza la TRY...CATCHconstrucción, si tiene una transacción activa y se produce un error, se pueden tomar varias rutas:
XACT_ABORT OFFy error de anulación de la declaración: la transacción aún está activa y el procesamiento continúa con la siguiente declaración , si corresponde.
XACT_ABORT OFFy la mayoría de los errores de cancelación de lotes: la transacción aún está activa y el procesamiento continúa con el siguiente lote , si corresponde.
XACT_ABORT OFFy ciertos errores de cancelación de lotes: la transacción se revierte y el procesamiento continúa con el siguiente lote , si corresponde.
XACT_ABORT ONy cualquier error: la transacción se revierte y el procesamiento continúa con el siguiente lote , si corresponde.
SIN EMBARGO, cuando se usa TRY...CATCH, los errores de aborto por lotes no abortan el lote, sino que transfieren el control al CATCHbloque. Cuando XACT_ABORTes OFF, la transacción seguirá siendo activa la gran mayoría de las veces, y usted tendrá que COMMIT, o lo más probable, ROLLBACK. Pero cuando encuentre ciertos errores de aborto por lotes (como con OPENQUERY), o cuando lo XACT_ABORTesté ON, la transacción estará en un nuevo estado, "no conmutable". En este estado no puede COMMIT, ni puede hacer ninguna operación DML. Todo lo que puedes hacer es ROLLBACKy SELECTdeclaraciones. Sin embargo, en este estado "incompatible", la transacción fue revertida cuando se produjo el error, y emitirlo ROLLBACKes solo una formalidad, pero debe hacerse.
Se puede usar una función, XACT_STATE , para determinar si una Transacción está activa, no se puede compartir o no existe. Se recomienda (por lo menos, algunos) verificar esta función en el CATCHbloque para determinar si el resultado es -1( es decir, no comunicable) en lugar de probar si @@TRANCOUNT > 0. Pero con XACT_ABORT ON, eso debería ser el único estado posible para estar, por lo que parece que las pruebas de @@TRANCOUNT > 0y XACT_STATE() <> 0son equivalentes. Por otro lado, cuando XACT_ABORThay OFFy hay una Transacción activa, entonces es posible tener un estado de cualquiera 1o -1en el CATCHbloque, lo que permite la posibilidad de emitir en COMMITlugar de ROLLBACK(aunque, no puedo pensar en un caso cuando alguien querríaCOMMITsi la transacción es commitable). Puede encontrar más información e investigación sobre el uso XACT_STATE()dentro de un CATCHbloque con XACT_ABORT ONmi respuesta a la siguiente pregunta de DBA.SE: ¿En qué casos se puede confirmar una transacción desde dentro del bloque CATCH cuando XACT_ABORT se establece en ON? . Tenga en cuenta que hay un pequeño error XACT_STATE()que hace que regrese falsamente 1en ciertos escenarios: XACT_STATE () devuelve 1 cuando se usa en SELECT con algunas variables del sistema pero sin la cláusula FROM
spNewBilling3emite un error, pero que no quieren volver rollospNewBilling2ospNewBilling1, a continuación, basta con retirar[begin|rollback|commit] transaction createSavebillinginvoicea partirspSavesomename.