Dalla documentazione RAISERROR (sottolineatura mia):
I livelli di gravità da 0 a 18 possono essere specificati da qualsiasi utente. I livelli di gravità da 19 a 25 possono essere specificati solo dai membri del ruolo predefinito del server sysadmin o dagli utenti con autorizzazioni ALTER TRACE. Per i livelli di gravità da 19 a 25, è richiesta l'opzione WITH LOG.
È molto probabile che il principale che stai eseguendo lo script non soddisfi questi criteri.
Non c'è niente di sbagliato nell'uso RAISERROR
; stai solo usando un livello di gravità eccessivo. Uso il livello 16 come predefinito per un errore che viene generato e la sequenza verrà terminata. Se vuoi essere più preciso, puoi seguire i livelli indicati dalla stessa Microsoft:
Ora, detto tutto ciò, a seconda del contesto dello script, l'utilizzo RAISERROR
potrebbe non essere sufficiente, in quanto non "esce" dallo script da solo (utilizzando livelli di gravità normali).
Per esempio:
RAISERROR(N'Test', 16, 1);
SELECT 1; /* Executed! */
Ciò sia genererà un errore e restituire un set di risultati.
Per terminare immediatamente lo script, preferisco usare RETURN
(l'uso di GOTO
costrutti di tipo è generalmente sconsigliato nella maggior parte dei circoli di programmazione in cui esistono alternative):
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
Oppure gestisci l'errore usando TRY/CATCH
, che farà saltare l'esecuzione al CATCH
blocco se la gravità è 11 o superiore:
BEGIN TRY
RAISERROR(N'Test', 16, 1);
SELECT 1; /* Not executed */
END TRY
BEGIN CATCH
SELECT 2; /* Executed */
END CATCH
BEGIN TRY
RAISERROR(N'Test', 10, 1);
SELECT 1; /* Executed */
END TRY
BEGIN CATCH
SELECT 2; /* Not executed */
END CATCH
Un problema separato è se lo script si estende su più batch - RETURN
uscirà solo dal batch :
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
SELECT 2; /* Executed! */
Per risolvere questo problema, puoi controllare @@ERROR
all'inizio di ogni batch:
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
IF (@@ERROR != 0)
RETURN;
SELECT 2; /* Not executed */
Modifica: come sottolinea correttamente Martin Smith nei commenti, questo funziona solo per 2 lotti. Per estendere a 3 o più batch, è possibile generare in sequenza errori di generazione in questo modo (nota: il GOTO
metodo non risolve questo problema poiché l'etichetta di destinazione deve essere definita all'interno del batch):
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
IF (@@ERROR != 0)
BEGIN
RAISERROR(N'Error already raised. See previous errors.', 16, 1);
RETURN;
END
SELECT 2; /* Not executed */
GO
IF (@@ERROR != 0)
BEGIN
RAISERROR(N'Error already raised. See previous errors.', 16, 1);
RETURN;
END
SELECT 3; /* Not executed */
Oppure, come sottolinea anche, puoi usare il SQLCMD
metodo se è appropriato per il tuo ambiente.