Lorsqu'il BACKUP DATABASEgénère une erreur, il en génère en fait deux. Malheureusement, TRY/CATCHn'est pas capable de capturer la première erreur; il ne capture que la deuxième erreur.
Je soupçonne que votre meilleur pari pour capturer la vraie raison derrière une sauvegarde échouée est d'automatiser vos sauvegardes via SQLCMD (avec -opour envoyer la sortie vers un fichier), SSIS, C #, PowerShell etc. Tout cela vous donnera un plus grand contrôle sur la capture de tous des erreurs.
La réponse SO dans le commentaire suggère d'utiliser DBCC OUTPUTBUFFER- bien que cela soit possible, cela ne semble pas du tout être un jeu d'enfant. N'hésitez pas à vous amuser avec cette procédure sur le site d'Erland Sommarskog , mais cela ne semble toujours pas bien fonctionner en combinaison avec TRY/CATCH.
La seule façon dont j'ai semblé être capable de capturer le message d'erreur spGET_LastErrorMessageest de savoir si l'erreur réelle est levée. Si vous l'enveloppez dans un, TRY/CATCHl'erreur est avalée et la procédure stockée ne fait rien:
BEGIN TRY
EXEC sp_executesql N'backup that fails...';
END TRY
BEGIN CATCH
EXEC dbo.spGet_LastErrorMessage;
END CATCH
Dans SQL Server <2012, vous ne pouvez pas relancer l'erreur vous-même, mais vous pouvez le faire dans SQL Server 2012 et versions ultérieures. Donc, ces deux variantes fonctionnent:
CREATE PROCEDURE dbo.dothebackup
AS
BEGIN
SET NOCOUNT ON;
EXEC sp_executesql N'backup that fails...';
END
GO
EXEC dbo.dothebackup;
EXEC dbo.spGET_LastErrorMessage;
Ou en 2012 et au-dessus, cela fonctionne, mais dans une large mesure, cela va à l'encontre du but de TRY/CATCH, car l'erreur d'origine est toujours levée:
CREATE PROCEDURE dbo.dothebackup2
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
EXEC sp_executesql N'backup that fails...';
END TRY
BEGIN CATCH
THROW;
END CATCH
END
GO
EXEC dbo.dothebackup2;
EXEC dbo.spGET_LastErrorMessage;
Dans ces deux cas, l'erreur est toujours renvoyée au client, bien sûr. Donc, si vous utilisez TRY/CATCHpour éviter cela, à moins qu'il n'y ait une faille à laquelle je ne pense pas, je crains que vous n'ayez à faire un choix ... soit donnez à l'utilisateur l'erreur et soyez en mesure de capturer des détails sur ou supprimez l'erreur et la raison réelle.