2013-02-22 8 views
7

Ho creato una stored procedure che esegue un numero di comandi per modificare i dati. Voglio solo commettere la transazione se tutto ha successo. Sto facendo questo utilizzando un blocco try-catch nel modo seguente (in cui il mio blocco CATCH nella cosa reale utilizza RAISERROR per restituire i messaggi di errore):SQL: Try/Catch non rileva un errore quando si tenta di accedere a una tabella che non riesce a trovare

BEGIN TRY 
    BEGIN TRANSACTION 
    UPDATE Table1 SET MyVarcharColumn = 'test' 
    UPDATE Table2 SET MyBitColumn = 1 
    UPDATE Table3 SET MyIntColumn = 42 
    COMMIT TRANSACTION 
END TRY 
CATCH 
    ROLLBACK TRANSACTION 
END CATCH 

che funziona il modo in cui voglio io. Se, ad esempio, imposto MyBitColumn su "b" anziché su 1, l'errore viene rilevato, il controllo passa al CATCH e la transazione non viene eseguita.

Un problema che ho notato è che se, ad esempio, Table3 non esiste nel database, allora si annulla (nome oggetto non valido), ma il blocco CATCH non viene mai eseguito e la transazione rimane aperta.

Voglio gestire questo per occuparmi di qualsiasi (remota) possibilità che un database venga modificato (o qualcosa accade dove questa stored procedure è stata aggiunta correttamente, ma una delle tabelle non lo è).

Come devo gestire questi casi di errore?

-Grazie per qualsiasi aiuto.

risposta

9

All'inizio dello script usano SET XACT_ABORT

SET XACT_ABORT ON 

Quando SET XACT_ABORT è ON, se un'istruzione Transact-SQL genera un errore di di run-time, l'intera transazione viene terminata e il rollback.

non credo che sara 'possibile:

i seguenti tipi di errori non sono gestite da un blocco CATCH quando si verificano allo stesso livello di esecuzione come il TRY ... CATCH construct:

  • Errori di compilazione, come errori di sintassi, che impediscono l'esecuzione di un batch.

  • Errori che si verificano durante la ricompilazione a livello di istruzione, , ad esempio errori di risoluzione del nome oggetto che si verificano dopo la compilazione a causa della risoluzione del nome posticipata .

Ref.

Il seguente esempio mostra come un errore di risoluzione nome oggetto generato da un'istruzione SELECT non ricade nel TRY ... CATCH costrutto, ma viene catturato dal blocco CATCH quando la stessa SELEZIONA istruzione viene eseguita all'interno di una stored procedure.

USE AdventureWorks2012; 
GO 

BEGIN TRY 
    -- Table does not exist; object name resolution 
    -- error not caught. 
    SELECT * FROM NonexistentTable; 
END TRY 
BEGIN CATCH 
    SELECT 
     ERROR_NUMBER() AS ErrorNumber 
     ,ERROR_MESSAGE() AS ErrorMessage; 
END CATCH 

L'errore non viene rilevata e il controllo passa fuori dal TRY ... CATCH costrutto al livello superiore.

+0

Grazie. È utile quell'impostazione che causa il rollback della transazione. Tuttavia, non esegue ancora ciò che si trova nel blocco CATCH dopo l'errore. Questo funziona per la mia applicazione (dal momento che l'errore viene trasmesso comunque verso l'alto) ma se qualcuno sta cercando di assicurarsi che il blocco CATCH venga eseguito per altri motivi questo non lo farebbe. – Luke

+0

Ah, capito, non sono catturati per quei tipi di errori in quel caso. Grazie! – Luke

-1
EXECUTE ('SELECT * FROM NonexistentTable');