Na documentação do RAISERROR (ênfase minha):
Os níveis de gravidade de 0 a 18 podem ser especificados por qualquer usuário. Os níveis de gravidade de 19 a 25 podem ser especificados apenas por membros da função de servidor fixa sysadmin ou usuários com permissões ALTER TRACE. Para níveis de gravidade de 19 a 25, a opção WITH LOG é necessária.
É muito provável que o diretor que você está executando o script não atenda a esses critérios.
Não há nada de errado em usar RAISERROR
; você está apenas usando um nível de gravidade excessivo. Eu uso o nível 16 como padrão para um erro gerado e a sequência será encerrada. Se você quiser ser mais preciso, pode seguir os níveis dados pela própria Microsoft:
Agora, tendo dito tudo isso, dependendo do contexto do script, o uso RAISERROR
pode não ser suficiente, pois não "sai" do script por si só (usando níveis normais de gravidade).
Por exemplo:
RAISERROR(N'Test', 16, 1);
SELECT 1; /* Executed! */
Isto irá tanto gerar um erro e retornar um conjunto de resultados.
Para finalizar o script imediatamente, prefiro usar RETURN
(o uso de GOTO
construções -type geralmente é desencorajado na maioria dos círculos de programação em que existem alternativas):
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
Ou lide com o erro usando TRY/CATCH
, o que fará com que a execução pule para o CATCH
bloco se a gravidade for 11 ou 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
Um problema separado é se o script abranger vários lotes - RETURN
sairá apenas do lote :
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
SELECT 2; /* Executed! */
Para corrigir isso, você pode verificar @@ERROR
no início 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 corretamente aponta nos comentários, isso funciona apenas para 2 lotes. Para estender para 3 ou mais lotes, é possível cascatear os erros de aumento dessa maneira (observação: o GOTO
método não resolve esse problema, pois o rótulo de destino deve ser definido no 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 */
Ou, como ele também aponta, você pode usar o SQLCMD
método se for apropriado para o seu ambiente.