【问题标题】:sp_send_dbmail executed from job fails with query result attached as file从作业执行的 sp_send_dbmail 失败,查询结果作为文件附加
【发布时间】:2013-02-13 07:18:58
【问题描述】:

我遇到了以下问题:当尝试发送带有查询结果的电子邮件时,通过执行普通查询使用 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'

有什么建议吗?

【问题讨论】:

  • 此外,即使我将这段代码包装到存储过程中,我最终还是一样
  • 所以一切正常 - 您只是不能为返回结果指定您想要的名称?你试过不同的名字吗?

标签: sql-server sql-server-2008 attachment sp-send-dbmail


【解决方案1】:

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

我调查过 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”发送邮件,它具有相同的“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

【讨论】:

  • 这并不能真正解决根本问题,而是使用了一个可能比所需权限多得多的帐户。此链接无需sa 帐户即可解决根本问题:stackoverflow.com/a/12963109/4416750
  • 当我将行添加到我的 SP 时,这对我来说不太有效,但它让我想到了将行添加到计划作业本身(在“步骤”的命令窗口中)我调用发送电子邮件的 SP 的对话框),这为我解决了问题。谢谢!
【解决方案2】:

我遇到了这个问题。我正在使用 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”并授予“select”权限来修复它。

【讨论】:

  • 非常非常有用的答案!! +1
【解决方案3】:

这对您很有帮助,谢谢。想分享我尝试使用将结果放在列中的 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'

【讨论】:

    【解决方案4】:
    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 来确保它从正确的位置运行查询。同样,这可能没有必要。

    不管最后是什么让它快乐,它与是否依恋无关。

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

        • 没有任何文件路径。文件是在执行 sp_send_dbmail 接受的查询时动态形成的。并填充其结果。
        • 我真的闻到了权限问题。您是否检查过您的用户和 sql server 代理帐户对您的数据库对象具有相同的权限?
        【解决方案7】:

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

        【讨论】:

          【解决方案8】:

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

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

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-01-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多