19

我遇到了以下问题:当尝试发送带有查询结果作为文件附加的电子邮件时,通过执行普通查询使用sp_send_dbmail一切似乎工作正常。

但是如果将相同的代码添加到 JobStep 并运行作业,它会失败。

工作经历中的错误说

错误格式化查询,可能是无效参数 [SQLSTATE 42000](错误 22050)。步骤失败。

但是当我注释掉引用文件附加的参数时,它又开始正常工作了。

exec msdb.dbo.sp_send_dbmail 
    @profile_name = 'profile_name', 
    @recipients  = 'some@mail.com',
    @body = 'body',
    @subject = 'subj',
    --Parameters that refers to attached file
    @attach_query_result_as_file = 1, 
    @query_result_header = 0,
    @query_result_no_padding = 1,
    @query = 'select 1',
    @query_attachment_filename = 'test.csv'

有什么建议么?

4

8 回答 8

31

我已经解决了这个问题。不知道为什么它会起作用,但永远不会少。:) 这绝对是关于安全性。

我调查过 SQL 代理代表域用户运行,比如DOMAIN\User。它具有服务器上的全套管理员权限(“sysadmin”服务器角色等)。SQL Server 本身在同一用户下运行。

包含调用sp_send_dbmail的作业步骤在相同的DOMAIN\User下运行。

我还发现,在运行sp_send_dbmail的查询部分时,它会尝试执行 exec xp_logininfo 'DOMAIN\User'来检查 Active Directory 是否该用户正常。惊喜:有些事情肯定不行。该检查以:

Msg 15404, Level 16, State 19, Server SQLC002INS02\SQLC002INS02, Line 1
Could not obtain information about Windows NT group/user 'DOMAIN\User.', error code 0x2.

这很可能意味着该用户的密码已过期或用户被锁定或该人的任何其他不愉快的事情。

我认为更改代理的用户是有风险的。所以我想代表“sa”发送邮件,该“sa”具有相同的“sysadmin”服务器角色,但 SQL 授权并省略了这个 AD 检查步骤。

看起来像一位冒充管理员的用户要求真正的管理员为他运行危险代码:)

所以这项工作的最终代码是第一步也是唯一的一步,如下所示:

execute as login = 'sa'
exec msdb.dbo.sp_send_dbmail 
    @profile_name = 'profile_name', 
    @recipients  = 'some@mail.com',
    @body = 'body',
    @subject = 'subj',
    --Parameters that refers to attached file
    @attach_query_result_as_file = 1, 
    @query_result_header = 0,
    @query_result_no_padding = 1,
    @query = 'select 1',
    @query_attachment_filename = 'test.csv'
revert
于 2013-02-28T13:02:47.357 回答
9

我有这个问题。我正在使用 SQL Server 2008 R2。通过添加选项,我收到了包含有关错误的更多信息的电子邮件:

@append_query_error = 1,

我收到了关于权限而不是我的查询的错误的电子邮件:

   Msg 916, Level 14, State 1, Server SERVER\INST01, 
Procedure GetSalesReport, Line 62
The server principal "CONTROLLEDNETWO\sql.service" is not able 
to access the database "MYDB01" under the current security co
ntext.

我的查询试图访问一些 SQL 代理没有权限的表(实际上在我的情况下它甚至没有访问权限)。

我通过 SQLSMS 通过将新用户“CONTROLLEDNETWO\sql.service”添加到数据库“MYDB01”并授予“选择”权限来修复它。

于 2014-11-10T17:33:05.890 回答
2

这一切都很有帮助,谢谢。想分享我尝试使用将结果放在列中的 excel(xls) 附件所做的事情。通过添加 query_result_no_padding = 1 和 query_result_separator= ' , ' 这对我有用。(即Tab,Tab中的勾号)

@query_result_header= 1,
@attach_query_result_as_file = 1,
@query_result_no_padding = 1,
@query_attachment_filename = 'TestPriceFlingerReport.xls',
@query_result_separator= '  ,   ',
@profile_name = 'Test Exchange Server'
于 2017-01-18T16:12:35.060 回答
1
EXEC msdb.dbo.sp_send_dbmail
    @profile_name = 'Main Profile',
    @recipients = 'me@vwp.com',
    @subject = 'Test',
    @body = 'this is a test',
    @execute_query_database = 'myTargetDatabase_mscrm',
    @query = N'SELECT * from myTargetDatabase_mscrm.dbo.SystemUserBase',
    @attach_query_result_as_file = 1,
    @query_attachment_filename = 'Test.txt'

作为参考,此失败反复显示为以域管理员身份调用,但以 local\sqladmin 身份运行。在关闭变量并尝试授予权限后,我在作业脚本中看到它仍在使用主数据库。我发现这个场景正盯着我看。它在 Step 的配置中。我将其更改为 msdb 并且它有效。请记住,我根据一些帖子将 select from myTable 更改为 select from myDatabase.dbo.myTable 。这可能有助于解决问题,也可能没有。我还使用了@execute_query_database 来确保它从正确的位置运行查询。同样,这可能没有必要。

不管最后是什么让它开心,都跟它有没有依恋没有关系。

于 2016-08-22T21:02:25.813 回答
1

在我的情况下,它无法识别属于数据库的表。一旦将 database.dbo.table 添加到查询中,它就可以工作了。

于 2017-05-24T18:29:50.383 回答
0

当您手动执行查询时,将使用您的凭据。当 SQL 代理执行相同的查询时,将使用 SQL 代理服务帐户的凭据。默认情况下,SQL Server 代理将使用 LocalSystem 帐户凭据。解决此问题的一种方法是使用有权访问 csv 目录\文件的用户更改运行 SQL Server 代理服务的用户。

于 2013-02-27T13:17:32.227 回答
0

我相信这个问题是由于在 SQL 2008 中实现的更改以及后来关于锁定 sp_send_dbmail 的安全性。仅当您将 qry 传递给 send_dbmail 以执行并通过电子邮件返回结果时才会发生这种情况。问题是错误消息具有误导性且不合适。一个好的解决方案是创建一个具有执行该查询所需的最低权限的 SQL 用户。例如,db_reader 或 db_writer 以及 db_owner(如果绝对必要)。并使该用户成为所有者。您还可以创建 SQL 凭据并将该 sql 作业配置为在该 SQL 凭据下运行。

于 2015-06-30T22:32:44.183 回答
0

我也有这个问题,并使用这里的大部分建议分两部分解决。

1)右键单击,作业上的“查看历史记录”显示失败详细信息,失败通知给出了作业运行下的用户名,因此我授予该用户对我的数据库的只读访问权限。

2) 我忘记指定DBName.dbo .MyTableName 并且只使用了 MyTableName。

顺便说一句,这些电子邮件都进入了我的垃圾邮件文件夹。

于 2016-02-24T16:49:23.697 回答