Implementare la gestione degli errori T-SQL
Un errore indica un problema o un problema rilevante che si verifica durante un'operazione di database. Gli errori possono essere generati dal motore di database di SQL Server in risposta a un evento o a un errore a livello di sistema; oppure è possibile generare errori dell'applicazione nel codice Transact-SQL.
Elementi degli errori del motore di database
Indipendentemente dalla causa, ogni errore è costituito dagli elementi seguenti:
- Numero errore - Numero univoco che identifica l'errore specifico.
- Messaggio di errore : testo che descrive l'errore.
- Gravità: numero compreso tra 1 e 25 indicante l'importanza.
- Stato : codice di stato interno per la condizione del motore di database.
- Procedura - Il nome della stored procedure o del trigger in cui si è verificato l'errore.
- Numero di riga : l'istruzione nel batch o nella routine ha generato l'errore.
Errori di sistema
Gli errori di sistema sono predefiniti ed è possibile visualizzarli nella vista di sistema sys.messages . Quando si verifica un errore di sistema, SQL Server può eseguire un'azione correttiva automatica, a seconda della gravità dell'errore. Ad esempio, quando si verifica un errore di gravità elevata, SQL Server può portare un database offline o persino arrestare il servizio motore di database.
Errori personalizzati
È possibile generare errori nel codice Transact-SQL per rispondere a condizioni specifiche dell'applicazione o per personalizzare le informazioni inviate alle applicazioni client in risposta agli errori di sistema. Questi errori dell'applicazione possono essere definiti inline in cui vengono generati oppure è possibile definirli nella tabella sys.messages insieme agli errori forniti dal sistema. I numeri di errore usati per gli errori personalizzati devono essere 50001 o versioni successive.
Per aggiungere un messaggio di errore personalizzato a sys.messages, usare sp_addmessage. L'utente per il messaggio deve essere un membro di uno dei ruoli predefiniti del server: sysadmin o serveradmin.
Questa è la sintassi sp_addmessage:
sp_addmessage [ @msgnum= ] msg_id , [ @severity= ] severity , [ @msgtext= ] 'msg'
[ , [ @lang= ] 'language' ]
[ , [ @with_log= ] { 'TRUE' | 'FALSE' } ]
[ , [ @replace= ] 'replace' ]
Di seguito è riportato un esempio di messaggio di errore personalizzato che usa questa sintassi:
sp_addmessage 50001, 10, N’Unexpected value entered’;
Inoltre, è possibile definire messaggi di errore personalizzati, i membri del ruolo del server sysadmin possono anche usare un parametro aggiuntivo , @with_log. Se impostato su TRUE, l'errore verrà registrato anche nel registro applicazioni di Windows. Qualsiasi messaggio scritto nel registro applicazioni di Windows viene scritto anche nel log degli errori di SQL Server. Si dovrebbe essere prudenti con l'uso dell'opzione @with_log perché gli amministratori di rete e di sistema tendono a non gradire le applicazioni che sono "verbose" nei log di sistema. Tuttavia, se l'errore deve essere intrappolato da un avviso, è necessario prima scrivere l'errore nel registro applicazioni di Windows.
Annotazioni
La generazione di errori di sistema non è supportata.
I messaggi possono essere sostituiti senza eliminarli prima usando l'opzione @replace = 'replace'.
I messaggi sono personalizzabili e possono essere aggiunti diversi per lo stesso numero di errore per più lingue, in base a un valore language_id.
Annotazioni
I messaggi in inglese sono language_id 1033.
Generare errori usando RAISERROR
Sia PRINT che RAISERROR possono essere usati per restituire informazioni o messaggi di avviso alle applicazioni. RAISERROR consente alle applicazioni di generare un errore che potrebbe essere rilevato dal processo chiamante.
RAISERROR
La possibilità di generare errori in T-SQL semplifica la gestione degli errori nell'applicazione, perché viene inviata come qualsiasi altro errore di sistema. RAISERROR viene usato per:
- Risolvere i problemi relativi al codice T-SQL.
- Controllare i valori dei dati.
- Restituisce messaggi contenenti testo variabile.
Annotazioni
L'uso di un'istruzione PRINT è simile alla generazione di un errore di gravità 10.
Di seguito è riportato un esempio di messaggio di errore personalizzato che usa RAISERROR.
RAISERROR (N'%s %d', -- Message text,
10, -- Severity,
1, -- State,
N'Custom error message number',
2)
Quando viene attivato, restituisce:
Custom error message number 2
Nell'esempio precedente %d è un segnaposto per un numero e %s è un segnaposto per una stringa. Inoltre, è consigliabile notare che un numero di messaggio non è stato menzionato. Quando vengono generati errori con stringhe di messaggio usando questa sintassi, hanno sempre il numero di errore 50000.
Generare errori usando THROW
L'istruzione THROW offre un metodo più semplice per generare errori nel codice. Gli errori devono avere un numero di errore di almeno 50000.
THROW
THROW differisce da RAISERROR in diversi modi:
- Gli errori generati da THROW sono sempre di gravità 16.
- I messaggi restituiti da THROW non sono correlati ad alcuna voce in sys.sysmessages.
- Gli errori generati da THROW causano solo interruzioni delle transazioni quando vengono usati insieme a SET XACT_ABORT ON e la sessione viene terminata.
THROW 50001, 'An Error Occured',0
Catturare i codici di errore usando @@Error
La maggior parte del codice di gestione degli errori tradizionale nelle applicazioni SQL Server è stata creata usando @@ERROR. La gestione strutturata delle eccezioni è stata introdotta in SQL Server 2005 e offre un'alternativa avanzata all'uso di @@ERROR. Verrà illustrato nella lezione successiva. Una grande quantità di codice di gestione degli errori di SQL Server esistente si basa su @@ERROR, quindi è importante comprendere come usarlo.
Errore: @@ERROR
@@ERROR è una variabile di sistema che contiene il numero di errore dell'ultimo errore che si è verificato. Una sfida significativa con @@ERROR è che il valore che contiene viene reimpostato rapidamente quando viene eseguita ogni istruzione aggiuntiva.
Si consideri ad esempio il codice seguente:
RAISERROR(N'Message', 16, 1);
IF @@ERROR <> 0
PRINT 'Error=' + CAST(@@ERROR AS VARCHAR(8));
GO
Ci si potrebbe aspettare che, quando il codice viene eseguito, restituisce il numero di errore in una stringa stampata. Tuttavia, quando viene eseguito il codice, restituisce:
Msg 50000, Level 16, State 1, Line 1
Message
Error=0
L'errore è stato generato ma il messaggio stampato è "Error=0". Nella prima riga dell'output è possibile notare che l'errore, come previsto, era effettivamente 50000, con un messaggio passato a RAISERROR. Ciò è dovuto al fatto che l'istruzione IF che segue l'istruzione RAISERROR è stata eseguita correttamente e ha causato la reimpostazione del valore @@ERROR. Per questo motivo, quando si lavora con @@ERROR, è importante acquisire il numero di errore in una variabile non appena viene generato e quindi continuare l'elaborazione con la variabile.
Esaminare il codice seguente che illustra quanto segue:
DECLARE @ErrorValue int;
RAISERROR(N'Message', 16, 1);
SET @ErrorValue = @@ERROR;
IF @ErrorValue <> 0
PRINT 'Error=' + CAST(@ErrorValue AS VARCHAR(8));
Quando questo codice viene eseguito, restituisce l'output seguente:
Msg 50000, Level 16, State 1, Line 2
Message
Error=50000
Il numero di errore viene segnalato correttamente.
Centralizzazione della gestione degli errori
Un altro problema significativo con l'uso di @@ERROR per la gestione degli errori è che è difficile centralizzare all'interno del codice T-SQL. La gestione degli errori tende a finire sparsa in tutto il codice. Sarebbe possibile centralizzare la gestione degli errori usando @@ERROR in qualche misura, usando etichette e istruzioni GOTO. Tuttavia, questo sarebbe disapprovato dalla maggior parte degli sviluppatori al giorno d'oggi come una cattiva pratica di programmazione.
Creare avvisi di errore
Per determinate categorie di errori, gli amministratori potrebbero creare avvisi di SQL Server, perché desiderano ricevere una notifica non appena si verificano. Ciò può essere applicato anche ai messaggi di errore definiti dall'utente. Ad esempio, potrebbe essere necessario generare un avviso ogni volta che viene riempito un log delle transazioni. Gli avvisi vengono comunemente usati per portare errori di gravità elevata (ad esempio gravità 19 o superiore) all'attenzione degli amministratori.
Generazione di avvisi
È possibile creare avvisi per messaggi di errore specifici. Il servizio di avviso si registra come servizio di callback con il servizio di registrazione eventi. Ciò significa che gli avvisi funzionano solo sugli errori registrati.
Esistono due modi per sollevare un errore e generare un avviso: è possibile usare l'opzione WITH LOG quando si solleva l'errore o il messaggio può essere modificato per essere registrato eseguendo sp_altermessage. L'opzione WITH LOG ha effetto solo sull'istruzione corrente. L'uso di sp_altermessage modifica il comportamento di errore per tutti gli usi futuri. La modifica degli errori di sistema tramite sp_altermessage è possibile solo da SQL Server 2005 SP3 o SQL Server 2008 SP1 e versioni successive.