执行Sql语句并将结果发送到电子邮件

use*_*625 4 sql-server sql-server-agent database-mail

我必须每天执行 SQL 语句并将结果通过电子邮件发送给 dba。我配置了数据库电子邮件。

下面是查询:

 SELECT
        account.accountID,
        account.name
    FROM
        account
        LEFT OUTER JOIN accountfeaturesetting afs 
            ON afs.accountid = account.accountid 
                and afs.featureid = 'Schedules' 
                and afs.settingid = 'EditReasons'
    WHERE
        ISNULL(afs.Value, '0') = '1'
        AND NOT EXISTS
 (SELECT 1 FROM program 
WHERE program.AccountID = account.AccountID
 AND program.Active = 1 AND 
(program.ScheduleEditReasonFlags <> 0 OR
 program.ScheduleEditReasonFields <> 0))
        AND account.IsMaster = 0
Run Code Online (Sandbox Code Playgroud)

为此,我创建了具有 2 个步骤的 Sql 作业:

  1. 执行选择语句
  2. 发送结果:

    Use MSDB
        EXEC msdb.dbo.sp_send_dbmail
            @profile_name = 'abc',
            @recipients = 'recipients@company.com',
            @subject = 'queryresultset',
            @body='testmail',
            @query_attachment_filename='warning.csv'
    
    Run Code Online (Sandbox Code Playgroud)

它抛出一个错误并且结果集没有附加查询。

错误:当没有为参数 @query 指定值时,参数 @attach_query_result_as_file 不能为 1 (true)。
必须指定查询以附加查询的结果。
[SQLSTATE 42000](错误 14625)

编辑:

Use MSDB
    EXEC msdb.dbo.sp_send_dbmail
        @profile_name = 'abc',
        @recipients = 'recipients@company.com',
        @subject = 'queryresultset',
        @body='testmail',
        @query_attachment_filename='warning.csv'
    DECLARE @msg VARCHAR(250);
    declare @query varchar(2048);
    SELECT @msg = 'Please refer to the attached spread sheet for the report.';  

    set @query='
        SELECT
        account.accountID,
        account.name
    FROM
        account
        LEFT OUTER JOIN accountfeaturesetting afs 
            ON afs.accountid = account.accountid 
                and afs.featureid = 'Schedules' 
                and afs.settingid = 'EditReasons'
    WHERE
        ISNULL(afs.Value, '0') = '1'
        AND NOT EXISTS
 (SELECT 1 FROM program 
WHERE program.AccountID = account.AccountID
 AND program.Active = 1 AND 
(program.ScheduleEditReasonFlags <> 0 OR
 program.ScheduleEditReasonFields <> 0))
        AND account.IsMaster = 0
        go';
        exec (@query)
Run Code Online (Sandbox Code Playgroud)

以上查询未采用 schedules 和 editreasons 值列。声明所有变量后,我仍然收到语法错误,例如:

declare @featureid varchar(100);
declare @settingid varchar(100);
declare @value varchar(100);
Run Code Online (Sandbox Code Playgroud)

Han*_*non 11

你的代码是倒退的。您正在发送电子邮件,然后生成查询结果。sp_send_dbmail 存储过程将为您运行查询,并将结果附加在电子邮件正文中或作为附件。

如果您不知道,Microsoft 在其网站上提供了大量、全面且免费的 SQL Server 文档。例如,sp_send_dbmail可在以下位置获得详细信息:https : //docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-send-dbmail-transact-sql

@query 参数记录为:

[ @query= ] 'query'
是要执行的查询。查询结果可以作为文件附加,也可以包含在电子邮件正文中。查询是 nvarchar(max) 类型,可以包含任何有效的 Transact-SQL 语句。请注意,查询是在单独的会话中执行的,因此调用 sp_send_dbmail 的脚本中的局部变量对查询不可用。

他们还有几个调用 的例子sp_send_dbmail,包括这个要点:

EXEC msdb.dbo.sp_send_dbmail  
    @profile_name = 'Adventure Works Administrator',  
    @recipients = 'yourfriend@Adventure-Works.com',  
    @query = 'SELECT COUNT(*) FROM AdventureWorks2012.Production.WorkOrder  
                  WHERE DueDate > ''2004-04-30''  
                  AND  DATEDIFF(dd, ''2004-04-30'', DueDate) < 2' ,  
    @subject = 'Work Order Count',  
    @attach_query_result_as_file = 1 ;  
Run Code Online (Sandbox Code Playgroud)

因此,您需要msdb.dbo.sp_send_dbmail像这样传递查询定义:

DECLARE @msg VARCHAR(250);
DECLARE @query varchar(2048);

SET @msg = 'Please refer to the attached spread sheet for the report.';  

SET @query='
    SELECT
        account.accountID,
        account.name
    FROM
        dbo.account
        LEFT OUTER JOIN dbo.accountfeaturesetting afs 
            ON afs.accountid = account.accountid 
                AND afs.featureid = ''Schedules'' 
                AND afs.settingid = ''EditReasons''
    WHERE
        ISNULL(afs.Value, ''0'') = ''1''
        AND NOT EXISTS 
            (
                SELECT 1 
                FROM dbo.program 
                WHERE program.AccountID = account.AccountID
                    AND program.Active = 1 
                    AND (
                        program.ScheduleEditReasonFlags <> 0 
                        OR program.ScheduleEditReasonFields <> 0
                        )
            )
        AND account.IsMaster = 0;';

EXEC msdb.dbo.sp_send_dbmail
    @profile_name = 'abc'
    , @recipients = 'recipients@company.com'
    , @subject = 'queryresultset'
    , @body= @msg
    , @body_format = 'TEXT'
    , @query = @query
    , @execute_query_database = 'MyDB'  
    , @attach_query_result_as_file = 1
    , @query_attachment_filename='warning.csv'
    , @query_result_header = 1
    , @query_result_width = 80
    , @query_result_separator = ' '
    , @exclude_query_output = 0
    , @append_query_error = 1
    , @query_no_truncate = 0
    , @query_result_no_padding = 0;
Run Code Online (Sandbox Code Playgroud)

还要注意包含的额外参数,这些参数控制各种输出因素,例如查询的格式等。

请注意,在@query上面的文本中,我“转义”了单引号以防止 SQL Server 将它们视为文字分隔符。本质上,出现在@query参数中的任何单引号都需要变成两个单引号。Erland Sommarskog 有一篇关于动态 SQL 和嵌套字符串的优秀文章。


Geo*_*e K 3

我相信你应该做类似的事情:

DECLARE @sub VARCHAR(100);
DECLARE @qry VARCHAR(1000);
DECLARE @msg VARCHAR(250);
DECLARE @query NVARCHAR(1000);
DECLARE @query_attachment_filename NVARCHAR(520);
SELECT @sub = 'TEST XML ATTACHMENT';
SELECT @msg = 'Please refer to the attached spread sheet for the report.';
SELECT @query = 'SET NOCOUNT ON;
            Select top 10 * from master..sysobjects WITH(NOLOCK)';
SELECT @query_attachment_filename = 'test.csv';
EXEC msdb.dbo.sp_send_dbmail
     @profile_name = 'SQLMAIL',
     @recipients = 'sqldba@sqldba.com',
     @copy_recipients = 'sqldba@sqldba.com',
     @body = @msg,
     @subject = @sub,
     @query = @query,
     @query_attachment_filename = @query_attachment_filename,
     @attach_query_result_as_file = 1,
     @query_result_header = 1,
     @query_result_width = 256,
     @query_result_separator = '   ',
     @query_result_no_padding = 1;
Run Code Online (Sandbox Code Playgroud)

参考: http ://sqlworkday.blogspot.ru/2010/12/how-to-send-csv-or-xls-file-as.html