De la documentación de RAISERROR (énfasis mío):
Cualquier usuario puede especificar los niveles de gravedad de 0 a 18. Los niveles de gravedad del 19 al 25 solo pueden ser especificados por miembros de la función fija de servidor sysadmin o usuarios con permisos ALTER TRACE. Para niveles de gravedad del 19 al 25, se requiere la opción WITH LOG.
Es muy probable que el director al que está ejecutando el script no cumpla con estos criterios.
No hay nada de malo en usar RAISERROR
; solo estás usando un nivel de severidad que es excesivo. Uso el nivel 16 como valor predeterminado para un error que se genera y la secuencia finalizará. Si desea ser más preciso, puede seguir los niveles dados por el propio Microsoft:
Ahora, habiendo dicho todo eso, dependiendo del contexto del guión, el uso RAISERROR
puede no ser suficiente, ya que no "sale" del guión por sí mismo (usando niveles de gravedad normales).
Por ejemplo:
RAISERROR(N'Test', 16, 1);
SELECT 1; /* Executed! */
Esto tanto generará un error y devolver un conjunto de resultados.
Para terminar el script de inmediato, prefiero usar RETURN
( GOTO
generalmente se desaconseja el uso de construcciones de tipo en la mayoría de los círculos de programación donde existen alternativas):
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
O maneje el error usando TRY/CATCH
, lo que hará que la ejecución salte al CATCH
bloque si la gravedad es 11 o superior:
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
Otro problema es si el script abarca varios lotes RETURN
, solo saldrá del lote :
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
SELECT 2; /* Executed! */
Para solucionar esto, puede verificar @@ERROR
al comienzo de cada lote:
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
IF (@@ERROR != 0)
RETURN;
SELECT 2; /* Not executed */
Editar: como Martin Smith señala correctamente en los comentarios, esto solo funciona para 2 lotes. Para extender a 3 o más lotes, puede colocar en cascada los errores de elevación de esta manera (nota: el GOTO
método no resuelve este problema ya que la etiqueta de destino debe definirse dentro del lote):
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 */
O, como él también señala, puede usar el SQLCMD
método si es apropiado para su entorno.