Назад | Перейти на главную страницу

Почему sp_send_dbmail не работает внутри заданий агента SQL?

У меня есть простой запрос, который я запускаю, чтобы отправлять уведомления по электронной почте администраторам учетных записей AD, если учетные записи отключены более 30 дней. Он отлично работает, когда я запускаю его самостоятельно, вошел в систему как SA, но он не работает при запуске внутри заданий агента SQL Server.

Вот запрос с замененными бизнес-элементами и именами объектов:

DECLARE @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 = 'This is the body text. Nothing interesting here.
', @recipients = 'me@mydomain.tld', @subject='Account status update', @query = @QueryString, @importance = 'High'

Когда я запускаю его как SA, сообщение отправляется. Внутри задания агента SQL Server я получаю эту ошибку:

Executed as user: DOMAIN\MemberOfDomainAdmins. Error formatting query, probably invalid parameters [SQLSTATE 42000] (Error 22050).  The step failed.

Пользователю домена, под которым выполняется задание, назначается роль db_owner в msdb и база данных, используемая для запроса, прикрепленного к сообщению. Его схема по умолчанию для обеих баз данных - dbo.

Ему также назначена роль системного администратора на сервере, и он является членом DatabaseMailuserRole в msdb. Он также имеет частный и публичный доступ к профилю почты базы данных, используемому запросом.

Я видел десятки примеров одной и той же проблемы в Интернете, но я уже предпринял шаги, которые исправили эту проблему в примерах, которые я видел. Что еще можно попробовать?

Я понял это сегодня утром. Проблема была в DATEADD функция. Когда он находится внутри оператора EXECUTE (именно так его запускает задание агента SQL Server), интервал должен быть определенной датой (день), а не одним из токенов («дд»).

Итак, эта функция:DATEDIFF(dd,DateDisabled,GETDATE())

Нужно было больше так: DATEDIFF(day,DateDisabled,GETDATE())

Там было несколько вызовов этой функции, но идею вы поняли.

Вот как я это понял: у меня SQL Server Management Studio записал задание как сценарий CREATE в новом документе редактора запросов. Как только я нашел шаг, который пытался выполнить, я скопировал его. Сочные кусочки выглядят примерно так:

@command = N'[my query]'

Я скопировал эту группу строк в новое окно и добавил DECLARE для командной переменной.

Наконец, я использовал EXECUTE (@command) AS USER = '[the user the job runs as]' чтобы увидеть, что произойдет. Выполнив запрос таким образом, я получил много более подробные сообщения об ошибках, чем я сделал из журнала для работы.

Я исправил это сейчас, и работа выполняется отлично.