2009-07-10 8 views
14

¿Try-Catch capturará todos los errores que @@ ERROR puede? En el siguiente fragmento de código, ¿vale la pena buscar @@ ERROR? ¿VOLVERÁ 1111 alguna vez?@@ ERROR y/o TRY - CATCH

SET XACT_ABORT ON 
BEGIN TRANSACTION 

BEGIN TRY 
    --do sql command here <<<<<<<<<<< 

    SELECT @[email protected]@ERROR 
    IF @Error!=0 
    BEGIN 
     IF XACT_STATE()!=0 
     BEGIN 
      ROLLBACK TRANSACTION 
     END 
     RETURN 1111 
    END 

END TRY 
BEGIN CATCH 

    IF XACT_STATE()!=0 
    BEGIN 
     ROLLBACK TRANSACTION 
    END 
    RETURN 2222 

END CATCH 

IF XACT_STATE()=1 
BEGIN 
    COMMIT 
END 

RETURN 0 

Respuesta

12

El siguiente artículo es una lectura obligada por Erland Sommarskog, SQL Server MVP: Implementing Error Handling with Stored Procedures

También tenga en cuenta que Your TRY block may fail, and your CATCH block may be bypassed

una cosa más: Procedimientos almacenados utilizando el control de errores de estilo antiguo y puntos de retorno puede no funcionar tan previsto cuando se utilizan junto con TRY ... CATCH bloques. Avoid mixing old and new styles of error handling.

+0

De acuerdo + 1 en ese – SQLMenace

+3

El artículo vinculado por Erland Sommarskog es para SQL Server 2000.Para su artículo sobre SQL Server 2005 ver aquí: http://www.sommarskog.se/error_handling_2005.html –

+0

@ RichardMarskell-Drackir ¿hay uno para SQL Server 2008? Quiero decir que el enlace dice 2005 y más tarde, pero ... – Apostrofix

8

TRY/CATCH traps more. Es inmensa y sorprendentemente mejor.

DECLARE @foo int 

SET @foo = 'bob' --batch aborting pre-SQL 2005 
SELECT @@ERROR 
GO 
SELECT @@ERROR --detects 245. But not much use, really if the batch was a stored proc 
GO 


DECLARE @foo int 
BEGIN TRY 
    SET @foo = 'bob' 
    SELECT @@ERROR 
END TRY 
BEGIN CATCH 
    SELECT ERROR_MESSAGE(), ERROR_NUMBER() 
END CATCH 
GO 

Usar TRY/CATCH en desencadenantes también funciona. Las retrotracciones del disparador solían ser aborto discontinuo: ya no se usa TRY/CATCH en el desencadenador.

Su ejemplo sería mejor si el/ROLLBACK BEGIN/COMMIT es adentro, no afuera, la construcción

0

No creo que el control alcanzará jamás la RETORNO statement-- una vez que estás en un bloque TRY , cualquier error generado transferirá el control al bloque CATCH. Sin embargo, hay algunos errores muy graves que pueden hacer que el lote o incluso la conexión aborten (Erland Sommarskog ha escrito sobre el tema de los errores en SQL Server here y here; desafortunadamente, no los ha actualizado para incluir TRY. ..CAPTURA). No estoy seguro si puedes atrapar ese tipo de error, pero entonces, @@ ERROR tampoco es bueno.

+3

No, no se puede detectar el error con una gravedad superior a 20. Además, no se pueden detectar las advertencias. – NYSystemsAnalyst

0

Según mi experiencia, los bloques TRY ... CATCH interceptarán todos los eventos que generarían errores (y, por lo tanto, establecer @@ ERROR en un valor distinto de cero). No puedo pensar en ninguna circunstancia en la que esto no se aplique. Entonces, no, el valor de retorno nunca se establecería en 1111, y no valdría la pena incluir esa verificación de @@ Error.

Sin embargo, el manejo de errores puede ser muy crítico y proteger mis apuestas para situaciones marginales tales como DTC, servidores enlazados, notificaciones o servicios de corretaje, y otras características de SQL con las que tengo muy poca experiencia. Si puedes, prueba tus situaciones más extrañas para ver qué sucederá realmente.

5

Try Catch que no retienen todo

Aquí hay un código para demostrar que

BEGIN TRY 
     BEGIN TRANSACTION TranA 
    DECLARE @cond INT; 
    SET @cond = 'A'; 
    END TRY 
    BEGIN CATCH 
    PRINT 'a' 
    END CATCH; 
    COMMIT TRAN TranA 

Servidor: Mensaje 3930, nivel 16, estado 1, línea 9 La transacción actual no puede ser cometido y no puede admitir operaciones que escriben en el archivo de registro. Revertir la transacción. Servidor: Msg 3998, nivel 16, estado 1, línea 1 Se detecta una transacción no confirmable al final del lote. La transacción se revierte.

+1

¿por qué no tener el inicio/compromiso dentro del intento? – gbn

+0

mismo resultado, necesita comprobar XACT_STATE para estar seguro debido a errores aún no viables y estado condenado – SQLMenace

+0

Es cierto, pero la confirmación dentro se transferiría al bloque catch y nunca se ejecutaría. Y también esperarías un retroceso en el bloque catch. Además, OP tiene SET XACT_ABORT ON que tiene una reversión automática. – gbn

0

El objetivo de "Try..Catch" es que no tenga que verificar @@ ERROR para cada instrucción.

Así que no vale la pena.

+0

Quieres decir que verificando '@@ ERROR' dentro de un' TRY ... CATCH' no vale la pena. Su declaración original no estaba clara. – Suncat2000