web-dev-qa-db-fra.com

Exécuter l'instruction Sql et envoyer le résultat par e-mail

Je dois exécuter l'instruction SQL tous les jours et envoyer le résultat à dba par e-mail. J'ai configuré la base de données e-mail.

Ci-dessous la requête:

 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

Pour cela j'ai créé un job Sql en 2 étapes:

  1. exécuter l'instruction select
  2. envoyer le résultat:

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

Il génère une erreur et le jeu de résultats n'est pas joint à la requête.

Erreur: le paramètre @attach_query_result_as_file ne peut pas être 1 (vrai) lorsqu'aucune valeur n'est spécifiée pour le paramètre @query.
Une requête doit être spécifiée pour joindre les résultats de la requête.
[SQLSTATE 42000] (Erreur 14625)

Éditer:

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)

La requête ci-dessus ne prend pas les colonnes de valeur des calendriers et des raisons de modification. Je reçois toujours une erreur de syntaxe après avoir déclaré toutes les variables comme:

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

Votre code est à l'envers. Vous envoyez l'e-mail, puis générez les résultats de la requête. La procédure stockée sp_send_dbmail exécutera la requête pour vous et ajoutera les résultats dans le corps de l'e-mail ou sous forme de pièce jointe.

Si vous n'êtes pas au courant, Microsoft dispose d'une documentation complète, complète et gratuite sur son site Web pour SQL Server. Par exemple, sp_send_dbmail est disponible en détail sur: https://docs.Microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-send-dbmail-transact-sql =

Le paramètre @query est documenté comme suit:

[@ query =] 'requête'
Est une requête à exécuter. Les résultats de la requête peuvent être joints en tant que fichier ou inclus dans le corps du message électronique. La requête est de type nvarchar (max) et peut contenir toutes les instructions Transact-SQL valides. Notez que la requête est exécutée dans une session distincte, les variables locales du script appelant sp_send_dbmail ne sont donc pas disponibles pour la requête.

Ils ont également plusieurs exemples d'appels sp_send_dbmail, y compris ce point saillant:

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 ;  

Vous devez donc passer la définition de la requête dans msdb.dbo.sp_send_dbmail comme ça:

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;

Notez également les paramètres supplémentaires inclus, qui contrôlent divers facteurs de sortie tels que la façon dont la requête est formatée, etc.

Remarque dans le @query texte ci-dessus, j'ai "échappé" les guillemets simples pour empêcher SQL Server de les considérer comme des délimiteurs littéraux. Essentiellement, les guillemets simples apparaissant à l'intérieur du @query le paramètre doit être transformé en deux guillemets simples. Erland Sommarskog a une excellente pièce sur SQL dynamique et chaînes imbriquées .

9
Max Vernon

Je pense que vous devriez faire quelque chose de similaire à ceci:

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;

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

3
George K