Je viens d'être surpris par quelque chose dans TSQL. Je pensais que si xact_abort était activé, j'appelais quelque chose comme
raiserror('Something bad happened', 16, 1);
arrêterait l'exécution de la procédure stockée (ou de tout lot).
Mais mon message d'erreur ADO.NET vient de prouver le contraire. J'ai reçu à la fois le message d'erreur de raiserror dans le message d'exception, ainsi que la prochaine chose qui s'est cassée après cela.
C'est ma solution de contournement (ce qui est mon habitude de toute façon), mais il ne semble pas que cela soit nécessaire:
if @somethingBadHappened
begin;
raiserror('Something bad happened', 16, 1);
return;
end;
Les documents disent ceci:
Lorsque SET XACT_ABORT est sur ON, si une instruction Transact-SQL génère une erreur d'exécution, la transaction entière est terminée et annulée.
Cela signifie-t-il que je dois utiliser une transaction explicite?
la source
RAISERROR
mettra en fait fin à l'exécution si la gravité est définie sur 17 ou 18, au lieu de 16.RAISERROR
ne mettra en fait pas fin à l'exécution si la gravité est définie sur 17 ou 18, au lieu de 16.Réponses:
Ceci est By Design TM , comme vous pouvez le voir sur Connect par la réponse de l'équipe SQL Server à une question similaire:
Oui, c'est un peu un problème pour certains qui espéraient
RAISERROR
qu'avec une gravité élevée (comme16
) serait la même chose qu'une erreur d'exécution SQL - ce n'est pas le cas.Votre solution de contournement concerne exactement ce que vous devez faire et l'utilisation d'une transaction explicite n'a aucun effet sur le comportement que vous souhaitez modifier.
la source
Si vous utilisez un bloc try / catch, un numéro d'erreur de raiserror de gravité 11-19 provoquera le saut de l'exécution vers le bloc catch.
Toute gravité supérieure à 16 est une erreur système. Pour illustrer le code suivant, configure un bloc try / catch et exécute une procédure stockée dont nous supposons qu'elle échouera:
Supposons que nous ayons une table [dbo]. [Erreurs] pour contenir les erreurs Supposons que nous ayons une procédure stockée [dbo]. [AssumeThisFails] qui échouera lorsque nous l'exécuterons
la source
Utilisez
RETURN
immédiatement aprèsRAISERROR()
et il n'exécutera pas la procédure plus loin.la source
rollback transaction
avant d'appelerreturn
.Comme indiqué sur la documentation pour
SET XACT_ABORT
, l'THROW
instruction doit être utilisée à la place deRAISERROR
.Les deux se comportent légèrement différemment . Mais lorsque
XACT_ABORT
est défini sur ON, vous devez toujours utiliser laTHROW
commande.la source