2009-07-10 14 views
14

Try-Catch acquisirà tutti gli errori che @@ ERROR può? Nel seguente frammento di codice, vale la pena controllare @@ ERROR? RITORNO 1111 si verificherà mai?@@ ERROR e/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 

risposta

12

L'articolo che segue è una lettura da Erland Sommarskog, SQL Server MVP: Implementing Error Handling with Stored Procedures

anche notare che Your TRY block may fail, and your CATCH block may be bypassed

Ancora una cosa: stored procedure utilizzando la gestione degli errori vecchio stile e punti di salvataggio potrebbe non funzionare come inteso quando vengono utilizzati insieme ai blocchi TRY ... CATCH. Avoid mixing old and new styles of error handling.

+0

concordato + 1 su quello – SQLMenace

+3

L'articolo collegato di Erland Sommarskog è per SQL Server 2000.Per il suo articolo su SQL Server 2005, consultare qui: http://www.sommarskog.se/error_handling_2005.html –

+0

@ RichardMarskell-Drackir ce n'è uno per SQL Server 2008? Intendo il link dice 2005 e versioni successive, ma .. – Apostrofix

8

TRY/CATCH intrappola di più. È incredibilmente e incredibilmente migliore.

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 

Anche l'utilizzo dei trigger TRY/CATCH è attivo. Anche i rollback di trigger erano abortiti in batch: non più se TRY/CATCH è utilizzato anche nel trigger.

Il tuo esempio sarebbe meglio se il/ROLLBACK BEGIN/COMMIT è dentro, non fuori, il costrutto

0

Non credo di controllo potrà mai raggiungere la RITORNO statement-- una volta che sei in un blocco try , qualsiasi errore generato trasferirà il controllo al blocco CATCH. Tuttavia, ci sono alcuni errori molto gravi che possono causare l'interruzione del batch o anche la connessione stessa (Erland Sommarskog ha scritto sull'argomento degli errori in SQL Server here e here - sfortunatamente, non li ha aggiornati per includere TRY. ..CATTURARE). Non sono sicuro che tu possa CATCARE questo tipo di errore, ma poi, anche @ ERROR non va bene.

+3

No, non è possibile rilevare l'errore con un livello di gravità superiore a 20. Inoltre, non è possibile rilevare gli avvisi. – NYSystemsAnalyst

0

È stata la mia esperienza che, come da documentazione online, i blocchi TRY ... CATCH cattureranno tutti gli eventi che genererebbero errori (e, quindi, impostano @@ ERROR su un valore diverso da zero). Non riesco a pensare a nessuna circostanza in cui ciò non si applicherebbe. Quindi no, il valore restituito non sarebbe mai stato impostato su 1111 e non sarebbe opportuno includerlo. @@ Controllo errori.

Tuttavia, la gestione degli errori può essere molto critica, e mi piacerebbe coprire le mie scommesse per le situazioni marginali, come DTC, i server collegati, servizi di notifica o di intermediazione, e altra caratteristica SQL che ho avuto poca esperienza con. Se puoi, prova le tue situazioni più bizzarre per vedere cosa accadrà realmente.

5

Try cattura non intrappola tutto

qui è un codice di dimostrare che

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

Server: Messaggio 3930, livello 16, stato 1, riga 9 L'operazione corrente non può essere commesso e non supporta le operazioni che scrivono nel file di registro. Rollback della transazione. Server: messaggio 3998, livello 16, stato 1, riga 1 La transazione non ammessa viene rilevata alla fine del batch. La transazione viene ripristinata.

+1

perché non avere il comando begin/commit all'interno del try? – gbn

+0

stesso risultato, è necessario verificare la presenza di XACT_STATE per gli errori ancora non intercambiabili e lo stato di sventura – SQLMenace

+0

Vero, ma il commit all'interno verrebbe trasferito al blocco catch e non verrebbe mai eseguito. E ti aspetteresti anche un rollback nel blocco catch. Inoltre, OP ha SET XACT_ABORT ON che ha un rollback automatico. – gbn

0

L'intero punto di "Try..Catch" è in modo che non è necessario controllare @ ERROR per ogni istruzione.

Quindi non ne vale la pena.

+0

Significa che cercare "@@ ERRORE" all'interno di "PROVA ... CATCH" non vale la pena. La tua dichiarazione originale non era chiara. – Suncat2000