Lors de l'émission d'une commande de sauvegarde dans une procédure stockée qui utilise un catch catch et un SQL dynamique, les messages d'erreur sont très généraux par rapport à l'exécution directe de la commande de sauvegarde.
Essayez / Catch dans SP:
begin try
execute sp_executesql @sql; -- a backup command
end try
begin catch
print ERROR_MESSAGE(); -- save to log, etc.
end catch
Résulte en
50000: usp_Backup: 117: BACKUP DATABASE se termine anormalement.
wheareas émettant la commande brute:
backup DATABASE someDb to disk...
Des résultats plus détaillés:
Erreur de recherche - Erreur de base de données SQL Server: une erreur d'E / S non récupérable s'est produite sur le fichier "H: \ FolderName \ Filename.bak:" 112 (il n'y a pas assez d'espace sur le disque.).
Existe-t-il un moyen d'attraper ces détails dans des variables au sein de la procédure stockée (pour se connecter, renvoyer à l'appelant, pour la logique de nouvelle tentative)? Il semble que les détails arrivent sur le canal de message mais je voudrais qu'ils soient disponibles dans le SP.
la source
Réponses:
Lorsqu'il
BACKUP DATABASE
génère une erreur, il en génère en fait deux. Malheureusement,TRY/CATCH
n'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
-o
pour 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 avecTRY/CATCH
.La seule façon dont j'ai semblé être capable de capturer le message d'erreur
spGET_LastErrorMessage
est de savoir si l'erreur réelle est levée. Si vous l'enveloppez dans un,TRY/CATCH
l'erreur est avalée et la procédure stockée ne fait rien: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:
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:Dans ces deux cas, l'erreur est toujours renvoyée au client, bien sûr. Donc, si vous utilisez
TRY/CATCH
pour é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.la source
Eh bien, je sais que c'est un vieux fil de discussion, et je sais que je suis sur le point de proposer un hack alambiqué, mais juste au cas où cela pourrait aider quelqu'un, voici: Puisque ces erreurs de sauvegarde sont enregistrées, vous pouvez utiliser xp_readerrorlog dans la capture bloquer pour gratter le journal des messages associés (erreur ou info). Vous pouvez rechercher des paramètres xp_readerrorlog sur Google, mais en bref, vous pouvez spécifier une chaîne de recherche et un filtre de temps de début qui sont utiles dans ce cas. Je ne sais pas si cela aiderait votre logique de nouvelle tentative, mais pour capturer des informations ou des erreurs pour la journalisation, j'ai trouvé quelque chose comme ça ...
HTH
la source
Vous pouvez enregistrer les détails de l'erreur dans une table. Vous pouvez également créer un fichier journal, mais cela peut nécessiter un CLR ou xp_cmdshell. Vous pouvez également envoyer des e-mails de base de données, mais cela peut entraîner des problèmes de spam et n'est pas un journal approprié.
Le tableau est le plus simple.
Regardez l'exemple de Jeremy Kadlec fourni dans le lien ci-dessous:
http://www.mssqltips.com/sqlservertip/1152/standardized-sql-server-error-handling-and-centralized-logging/
la source
CATCH
. En effet, seul le dernier message d'erreur est renvoyé dansERROR_MESSAGE()
...