101 votes

Comment relancer la même exception dans SQL Server

Je veux relancer la même exception dans SQL Server qui vient de se produire dans mon bloc try. Je suis capable de renvoyer le même message mais je veux renvoyer la même erreur.

DÉBUT TRANSACTION
    BEGIN TRY
        INSÉRER DANS Tags.tblDomain (DomainName, SubDomainId, DomainCode, Description)
            VALEURS (@DomainName, @SubDomainId, @DomainCode, @Description)
        VALIDER TRANSACTION
    END TRY

    BEGIN CATCH
        déclarer @gravité int; 
        déclarer @état int;

        sélectionner @gravité=error_severity(), @état=error_state();

        RAISERROR(@@Error,@ErrorSeverity,@état);
        ANNULER TRANSACTION
    END CATCH

RAISERROR(@@Error, @ErrorSeverity, @état);

Cette ligne affichera une erreur, mais je veux une fonctionnalité semblable à cela. Cela lève une erreur avec le numéro d'erreur 50000, mais je veux que le numéro d'erreur lancé soit celui que je passe @@error,

Je veux capturer ce numéro d'erreur au niveau du frontend.

c'est-à-dire

catch (SqlException ex)
{
    if ex.number==2627
    MessageBox.show("Duplicate value cannot be inserted");
}

Je veux cette fonctionnalité. qui ne peut pas être réalisée en utilisant raiseerror. Je ne veux pas donner de message d'erreur personnalisé à l'arrière-plan.

RAISEERROR devrait renvoyer l'erreur mentionnée ci-dessous lorsque je passe ErrorNo à lancer dans catch

Msg 2627, Niveau 14, État 1, Procédure spOTest_DomainInsert,

Ligne 14 Violation de la contrainte de clé UNIQUE 'UK_DomainCode'. Impossible d'insérer une clé en double dans l'objet 'Tags.tblDomain'. La déclaration a été terminée.

ÉDITION:

Quels pourraient être les inconvénients de ne pas utiliser de bloc try catch si je veux que l'exception soit gérée au frontend en considérant que la procédure stockée contient plusieurs requêtes qui doivent être exécutées?

158voto

Michael Points 1971

SQL 2012 introduit la déclaration throw :

http://msdn.microsoft.com/en-us/library/ee677615.aspx

Si la déclaration THROW est spécifiée sans paramètres, elle doit apparaître à l'intérieur d'un bloc CATCH. Cela cause l'exception attrapée à être levée.

BEGIN TRY
    BEGIN TRANSACTION
    ...
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION;
    THROW
END CATCH

139voto

Ben Gripka Points 4885

Voici un exemple de code propre et fonctionnel pour annuler une série d'instructions en cas d'erreur et signaler le message d'erreur.

begin try
    begin transaction;

    ...

    commit transaction;
end try
begin catch
    if @@trancount > 0 rollback transaction;
    throw;
end catch

Avant SQL 2012

begin try
    begin transaction;

    ...

    commit transaction;
end try
begin catch
    declare @ErrorMessage nvarchar(max), @ErrorSeverity int, @ErrorState int;
    select @ErrorMessage = ERROR_MESSAGE() + ' Ligne ' + cast(ERROR_LINE() as nvarchar(5)), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE();
    if @@trancount > 0 rollback transaction;
    raiserror (@ErrorMessage, @ErrorSeverity, @ErrorState);
end catch

10voto

nzeemin Points 46

Rethrowing inside the CATCH block (code pre-SQL2012, utiliser l'instruction THROW pour SQL2012 et ultérieur):

DECLARE
    @ErrorMessage nvarchar(4000) = ERROR_MESSAGE(),
    @ErrorNumber int = ERROR_NUMBER(),
    @ErrorSeverity int = ERROR_SEVERITY(),
    @ErrorState int = ERROR_STATE(),
    @ErrorLine int = ERROR_LINE(),
    @ErrorProcedure nvarchar(200) = ISNULL(ERROR_PROCEDURE(), '-');
SELECT @ErrorMessage = N'Error %d, Niveau %d, État %d, Procédure %s, Ligne %d, ' + 'Message: ' + @ErrorMessage;
RAISERROR (@ErrorMessage, @ErrorSeverity, 1, @ErrorNumber, @ErrorSeverity, @ErrorState, @ErrorProcedure, @ErrorLine)

5voto

Rob Farley Points 9042

Je pense que vos choix sont:

  • Ne pas attraper l'erreur (le laisser remonter)
  • Lever une erreur personnalisée

À un moment donné, SQL introduira probablement une commande de réémission, ou la capacité d'attraper uniquement certaines erreurs. Mais pour l'instant, utilisez une solution de contournement. Désolé.

1voto

gbn Points 197263

Vous ne pouvez pas : seul le moteur peut générer des erreurs de moins de 50000. Tout ce que vous pouvez faire, c'est jeter une exception qui semble être celle-ci...

Veuillez voir ma réponse ici s'il vous plaît

Le demandeur ici a utilisé des transactions côté client pour faire ce qu'il voulait, ce que je trouve un peu stupide...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X