5 votes

Pourquoi sp_send_dbmail échoue-t-il à l'intérieur des tâches de l'Agent SQL ?

J'ai une requête simple que j'exécute pour envoyer des notifications par e-mail à nos administrateurs de compte AD lorsque des comptes sont désactivés depuis plus de 30 jours. Cela fonctionne parfaitement bien lorsque je l'exécute en tant qu'administrateur système (SA), mais cela échoue lorsqu'il est exécuté à l'intérieur des tâches de l'Agent SQL Server.

Voici la requête, avec des éléments spécifiques à l'entreprise et des noms d'objets remplacés :

DÉCLARE @QueryString varchar(max)
SET @QueryString = 'Select TrackingTable.Username FROM dbName.Schema.TrackingTable inner join dbName.Schema.viewName on DisabledAccounts.username = viewName.username WHERE DATEDIFF(dd,DateDisabled,GETDATE()) > 25 AND viewName.OU = ''InactiveAccounts'''
EXEC msdb.dbo.sp_send_dbmail  @profile_name = 'Profile', @body = 'Ceci est le texte du corps. Rien d'intéressant ici.
', @recipients = 'moi@mondomaine.tld', @subject='Mise à jour de l'état du compte', @query = @QueryString, @importance = 'Élevée'

Lorsque je l'exécute en tant qu'administrateur système (SA), le message est envoyé. À l'intérieur d'une tâche de l'Agent SQL Server, j'obtiens cette erreur :

Exécuté en tant qu'utilisateur : DOMAIN\MemberOfDomainAdmins. Erreur de formatage de la requête, probablement des paramètres invalides [SQLSTATE 42000] (Erreur 22050).  La tâche a échoué.

L'utilisateur de domaine sous lequel s'exécute la tâche est assigné le rôle db_owner sur msdb et la base de données utilisée pour la requête attachée au message. Son schéma par défaut sur les deux bases de données est dbo.

Il est également assigné le rôle sysadmin sur le serveur et est membre du rôle DatabaseMailuserRole sur msdb. Il a également un accès privé et public au profil de messagerie de base de données utilisé par la requête.

J'ai vu des dizaines d'exemples du même problème en ligne, mais j'ai déjà suivi les étapes qui ont résolu ce problème dans les exemples que j'ai vus. Que puis-je essayer d'autre ?

6voto

Ben Wyatt Points 311

J'ai compris ce matin. Le problème était avec la fonction DATEADD. Lorsqu'elle est à l'intérieur d'une instruction EXECUTE (c'est ainsi qu'une tâche SQL Server Agent l'exécuterait), l'intervalle doit être une partie de date spécifique (jour), pas l'un des jetons ("dd").

Donc, cette fonction : DATEDIFF(dd,DateDisabled,GETDATE())

Devait ressembler plus à ceci : DATEDIFF(day,DateDisabled,GETDATE())

Il y avait plusieurs appels à cette fonction là-bas, mais vous avez compris l'idée.

Voici comment j'ai compris : j'ai demandé à SQL Server Management Studio de scripter le travail sous forme d'un script CREATE dans un nouveau document de l'éditeur de requêtes. Une fois que j'ai trouvé l'étape que je voulais exécuter, je l'ai copiée. Les parties intéressantes ressemblent à ceci :

@command = N'[ma requête]'

J'ai copié ce groupe de lignes dans une nouvelle fenêtre et j'ai ajouté un DECLARE pour la variable de commande.

Enfin, j'ai utilisé EXECUTE (@command) AS USER = '[l'utilisateur sous lequel la tâche s'exécute]' pour voir ce qui se passerait. En exécutant la requête de cette manière, j'ai obtenu des messages d'erreur beaucoup plus détaillés que ceux du journal de la tâche.

Je l'ai corrigé maintenant, et la tâche s'exécute parfaitement.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X