web-dev-qa-db-ja.com

SQLステートメントを実行し、結果をメールで送信する

毎日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

このために、2つのステップを持つSQLジョブを作成しました。

  1. selectステートメントを実行する
  2. 結果を送信:

    Use MSDB
        EXEC msdb.dbo.sp_send_dbmail
            @profile_name = 'abc',
            @recipients = '[email protected]',
            @subject = 'queryresultset',
            @body='testmail',
            @query_attachment_filename='warning.csv'
    

エラーがスローされ、結果セットがクエリに添付されていません。

エラー:パラメータ@queryに値が指定されていない場合、パラメータ@attach_query_result_as_fileを1(真)にすることはできません。
クエリの結果を添付するには、クエリを指定する必要があります。
[SQLSTATE 42000](エラー14625)

編集:

Use MSDB
    EXEC msdb.dbo.sp_send_dbmail
        @profile_name = 'abc',
        @recipients = '[email protected]',
        @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)

上記のクエリは、スケジュールとeditreasons値列を取得していません。次のようにすべての変数を宣言した後も、構文エラーが発生します。

declare @featureid varchar(100);
declare @settingid varchar(100);
declare @value varchar(100);
3
user120625

あなたのコードは逆です。メールを送信し、クエリ結果を生成します。 sp_send_dbmailストアドプロシージャがクエリを実行し、結果を電子メールの本文または添付ファイルのいずれかに追加します。

ご存知ない場合のために、MicrosoftのWebサイトには、SQL Serverに関する広範で包括的な無料のドキュメントがあります。たとえば、sp_send_dbmailは次の場所で詳細に入手できます。 https://docs.Microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-send-dbmail -transact-sql

@queryパラメータは次のように文書化されています。

[@ query =] 'クエリ'
実行するクエリです。クエリの結果は、ファイルとして添付するか、電子メールメッセージの本文に含めることができます。クエリのタイプはnvarchar(max)で、有効なTransact-SQLステートメントを含めることができます。クエリは別のセッションで実行されるため、sp_send_dbmailを呼び出すスクリプトのローカル変数はクエリで使用できないことに注意してください。

また、sp_send_dbmailの呼び出しの例がいくつかあります。

EXEC msdb.dbo.sp_send_dbmail  
    @profile_name = 'Adventure Works Administrator',  
    @recipients = '[email protected]',  
    @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 ;  

したがって、次のようにクエリ定義を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 = '[email protected]'
    , @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;

また、クエリのフォーマット方法など、さまざまな出力要素を制御する追加のパラメータが含まれていることにも注意してください。

上記の@queryのテキストでは、SQLサーバーが単一引用符をリテラル区切り文字と見なさないように、単一引用符を「エスケープ」しています。基本的に、@queryパラメータ内に現れる単一引用符は、2つの単一引用符に変換する必要があります。 Erland Sommarskogは 動的SQLとネストされた文字列 に関する優れた部分を持っています。

9
Max Vernon

私はあなたがこれに似た何かをしているべきだと信じています:

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 = '[email protected]',
     @copy_recipients = '[email protected]',
     @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;

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

3
George K