Je veux renvoyer la même exception sur le serveur SQL qui s'est produite dans mon bloc try. Je suis capable de lancer le même message mais je veux lancer la même erreur.
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO Tags.tblDomain
(DomainName, SubDomainId, DomainCode, Description)
VALUES(@DomainName, @SubDomainId, @DomainCode, @Description)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
declare @severity int;
declare @state int;
select @severity=error_severity(), @state=error_state();
RAISERROR(@@Error,@ErrorSeverity,@state);
ROLLBACK TRANSACTION
END CATCH
RAISERROR(@@Error, @ErrorSeverity, @state);
Cette ligne affichera une erreur, mais je veux une fonctionnalité quelque chose comme ça. Cela soulève une erreur avec le numéro d'erreur 50000, mais je veux qu'un nombre erroné soit généré que je passe @@error
,
Je veux capturer cette erreur non à l'interface
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 atteint en utilisant raiseerror. Je ne veux pas donner un message d'erreur personnalisé à l'arrière.
RAISEERROR devrait renvoyer l'erreur mentionnée ci-dessous lorsque je passe ErrorNo à lancer
Msg 2627, Level 14, State 1, Procedure spOTest_DomainInsert,
Ligne 14 Violation de la contrainte UNIQUE KEY 'UK_DomainCode'. Impossible d'insérer une clé en double dans l'objet 'Tags.tblDomain'. La déclaration a été terminée.
MODIFIER:
Quel peut être l’inconvénient de ne pas utiliser try catch block si je veux que l’exception soit gérée au niveau frontal car la procédure stockée contient plusieurs requêtes à exécuter
Voici un exemple de code propre entièrement fonctionnel permettant d'annuler une série d'instructions si une erreur se produit et de signaler le message d'erreur.
begin try
begin transaction;
...
commit transaction;
end try
begin catch
declare @ErrorMessage nvarchar(max), @ErrorSeverity int, @ErrorState int;
select @ErrorMessage = ERROR_MESSAGE() + ' Line ' + cast(ERROR_LINE() as nvarchar(5)), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE();
rollback transaction;
raiserror (@ErrorMessage, @ErrorSeverity, @ErrorState);
end catch
SQL 2012 introduit l'instruction throw:
http://msdn.Microsoft.com/en-us/library/ee677615.aspx
Si l'instruction THROW est spécifiée sans paramètre, elle doit apparaître à l'intérieur d'un bloc CATCH. Cela provoque l’exception interceptée.
BEGIN TRY
BEGIN TRANSACTION
...
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
THROW
END CATCH
Renvoi à l'intérieur du bloc CATCH (code pré-SQL 2012, utilisez l'instruction THROW pour SQL 2012 et versions ultérieures):
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, Level %d, State %d, Procedure %s, Line %d, ' + 'Message: ' + @ErrorMessage;
RAISERROR (@ErrorMessage, @ErrorSeverity, 1, @ErrorNumber, @ErrorSeverity, @ErrorState, @ErrorProcedure, @ErrorLine)
Je pense que vos choix sont:
À un moment donné, SQL introduira probablement une commande reraise ou la possibilité d’attraper certaines erreurs seulement. Mais pour l'instant, utilisez une solution de contournement. Pardon.
Vous ne pouvez pas: seul le moteur peut générer des erreurs inférieures à 50000. Tout ce que vous pouvez faire est de lever une exception à laquelle ressemble à cela ...
Voir ma réponse ici s'il vous plaît
L’interrogateur a utilisé ici des transactions côté client pour faire ce qu’il voulait, ce qui, à mon avis, est un peu idiot ...
Étant donné que vous n'avez pas encore migré vers 2012, une solution pour implémenter le code d'erreur original consiste à utiliser la partie message texte de l'exception que vous (ré) envoyez du bloc catch. N'oubliez pas qu'il peut contenir une structure, par exemple un texte XML que votre code d'appelant analysera dans son bloc catch.
Pour arrêter l'exécution dans une procédure stockée après une erreur et remettre l'erreur au programme appelant, suivez chaque instruction susceptible de générer une erreur avec le code suivant:
If @@ERROR > 0
Return
J'ai moi-même été surpris d'apprendre que l'exécution d'une procédure stockée peut continuer après une erreur. Ne pas s'en rendre compte peut rendre difficile la traçabilité des bogues.
Ce type de traitement des erreurs est parallèle (avant .Net) Visual Basic 6. Dans l'attente de la commande Lancer dans SQL Server 2012.
Ok, c'est une solution de contournement ... :-)
DECLARE @Error_Number INT
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO Test(Id, Name) VALUES (newID(),'Ashish')
/* Column 'Name' has unique constraint on it*/
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER()
--RAISERROR (@ErrorMessage,@Severity,@State)
ROLLBACK TRAN
END CATCH
Si vous notez le bloc catch, il ne soulève pas l'erreur mais renvoie le numéro d'erreur réel (et annule également la transaction). Désormais, dans votre code .NET, au lieu d'attraper l'exception , Si vous utilisez ExecuteScalar (), vous obtenez le numéro d'erreur réel que vous souhaitez et affichez le numéro approprié.
int errorNumber=(int)command.ExecuteScalar();
if(errorNumber=<SomeNumber>)
{
MessageBox.Show("Some message");
}
J'espère que cela t'aides,
EDIT: - Juste une note, si vous voulez obtenir le nombre d'enregistrements affectés et essayez d'utiliser ExecuteNonQuery, la solution ci-dessus risque de ne pas fonctionner pour vous. Sinon, je pense que cela conviendrait à ce dont vous avez besoin. Faites le moi savoir.
Vous pouvez également créer une procédure stockée wrapper pour les scénarios dans lesquels vous souhaitez que l'instruction SQL soit exécutée dans la transaction et que l'erreur soit renvoyée dans votre code.
CREATE PROCEDURE usp_Execute_SQL_Within_Transaction
(
@SQL nvarchar(max)
)
AS
SET NOCOUNT ON
BEGIN TRY
BEGIN TRANSACTION
EXEC(@SQL)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
DECLARE @ErrorMessage nvarchar(max), @ErrorSeverity int, @ErrorState int
SELECT @ErrorMessage = N'Error Number: ' + CONVERT(nvarchar(5), ERROR_NUMBER()) + N'. ' + ERROR_MESSAGE() + ' Line ' + CONVERT(nvarchar(5), ERROR_LINE()), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE()
ROLLBACK TRANSACTION
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState)
END CATCH
GO
-- Test it
EXEC usp_Execute_SQL_Within_Transaction @SQL = 'SELECT 1; SELECT 2'
EXEC usp_Execute_SQL_Within_Transaction @SQL = 'SELECT 1/0; SELECT 2'
EXEC usp_Execute_SQL_Within_Transaction @SQL = 'EXEC usp_Another_SP'