使用sp_send_dbmail使用消息动态地将电子邮件发送给多个收件人

时间:2017-07-07 08:26:43

标签: sql sql-server sql-server-2008 sql-server-2005 sql-server-2012

其实我希望向会员发送生日祝福。我正在动态获取收件人列表。通过以下查询,我可以向会员发送问候语。

<ul>

因此,如果@emails有多个收件人,我该如何将邮件发送给每个成员。

DECLARE @emails VARCHAR(500)
DECLARE @bodycontent VARCHAR(500)
SET @emails = '' 
SET @bodycontent = ''
use dnname
SELECT @emails = @emails + cm.PersonalEmail + ';' FROM tblIndividualMst  im
       inner join tblContactMst cm on cm.ContactID = im.ContactID
       where im.GroupID = 4673 and im.DateOfBirth = CONVERT(VARCHAR(10),GETDATE(),110)
DECLARE @recipList VARCHAR(500)
SET @recipList =  (select SUBSTRING(@emails, 0, LEN(@emails)))
SELECT @bodycontent = 'Happy BirthDay to'+ ' ' + + @bodycontent + 
       im.FullName + '' FROM tblIndividualMst  im
       inner join tblContactMst cm on cm.ContactID = im.ContactID
       where im.GroupID = 4673 and im.DateOfBirth = CONVERT(VARCHAR(10),GETDATE(),110)
use msdb
EXEC sp_send_dbmail @profile_name='eMail Profile',
    @recipients=@recipList,
    @subject='Happy Birthday',
    @body=@bodycontent, 
    @body_format = 'text'

那么,我该如何修改我的查询。任何帮助表示感谢,谢谢!

2 个答案:

答案 0 :(得分:1)

以下是一些观察......

  1. 您尚未在代码中的任何位置声明@Count。它需要声明为INT并设置为0
  2. 在你的WHILE LOOP中,你没有递增@Count所以这个循环是无限的
  3. 我会@emails varchar(max)以避免截断收件人列表
  4. 据我所知,
  5. @recipList毫无意义...你将它设置为substring从0开始并且在所有电子邮件的整个长度上...这是相同的说set @recipList = @emails
  6. 您的while循环不是逻辑构造的,您希望它如何工作。您的意图似乎是发送一封包含所有生日姓名的电子邮件。首先,我会在@body中将这些名称分开。其次,根本不需要循环。移除WHILE循环,因为您需要做的只是将电子邮件发送到您已构建的@recipList列表,并使用您正在连接的@bodycontent
  7. 所有人都说了......你的代码可以简化为下面的代码,这应该可行。

    use dnname
    
    DECLARE @emails VARCHAR(max)
    DECLARE @bodycontent VARCHAR(max)
    DECLARE @people varchar(max) 
    SET @emails = '' 
    SET @people = ''
    SET @bodycontent = ''
    
    
    
    SELECT @emails = @emails + cm.PersonalEmail + ';' FROM tblIndividualMst  im
           inner join tblContactMst cm on cm.ContactID = im.ContactID
           where im.GroupID = 4673 and im.DateOfBirth = CONVERT(VARCHAR(10),GETDATE(),110)
    
    
    SELECT @people = @people + im.FullName + ', ' 
           FROM tblIndividualMst  im
           inner join tblContactMst cm on cm.ContactID = im.ContactID
           where im.GroupID = 4673 and im.DateOfBirth = CONVERT(VARCHAR(10),GETDATE(),110)
    
    SELECT @bodycontent = 'Happy BirthDay to '+ @people
    
    EXEC msdb.dbo.sp_send_dbmail 
                               @profile_name='eMail Profile',
                               @recipients=@emails,
                               @subject='Happy Birthday',
                               @body=@bodycontent,  
                               @body_format = 'text'
    

    如果您想为每个人发送一封个性化电子邮件......您可以使用光标

    use dnname
    
    DECLARE @emails VARCHAR(4000)
    DECLARE @bodycontent VARCHAR(max)
    DECLARE @people varchar(4000) 
    SET @emails = '' 
    SET @people = ''
    SET @bodycontent = ''
    
    DECLARE emailCursor CURSOR FOR
    
    SELECT cm.PersonalEmail,im.FullName 
    FROM tblIndividualMst  im
    inner join tblContactMst cm on cm.ContactID = im.ContactID
    where im.GroupID = 4673 and im.DateOfBirth = CONVERT(VARCHAR(10),GETDATE(),110)
    
    OPEN emailCursor
    FETCH NEXT FROM emailCursor INTO  @emails, @people
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
    
    SET @bodycontent = 'Happy BirthDay to '+ @people
    
    EXEC msdb.dbo.sp_send_dbmail 
                               @profile_name='eMail Profile',
                               @recipients=@emails,
                               @subject='Happy Birthday',
                               @body=@bodycontent,  
                               @body_format = 'text'
    
    FETCH NEXT FROM emailCursor INTO  @emails, @people
    
    
    
    END
    CLOSE emailCursor
    DEALLOCATE emailCursor
    

答案 1 :(得分:0)

我个人反对在SQL中使用循环,因此尽量避免使用它们。这背后的想法是尽可能少地发表声明。在这种情况下,我生成一个动态SQL并执行它。

DECLARE @SQL NVARCHAR(MAX);
SELECT @SQL = CAST((
    SELECT [text()] = REPLACE(REPLACE('
        EXEC msdb.dbo.sp_send_dbmail 
            @profile_name=''eMail Profile'',
            @recipients=''{email}'',
            @subject=''Happy Birthday'',
            @body=''Happy BirthDay to {fullname}'',  
            @body_format = ''text'';
    '
    ,'{fullname}',im.FullName)
    ,'{email}',cm.PersonalEmail)
    FROM tblIndividualMst  im
        INNER JOIN tblContactMst cm 
            ON cm.ContactID = im.ContactID
    WHERE im.GroupID = 4673 
        AND im.DateOfBirth = CAST(GETDATE() AS DATE)
    FOR XML PATH('')
) AS NVARCHAR(max));
EXEC sp_executesql @SQL;

让我解释一下我在这里做的事情:

声明@SQL并将查询结果分配给NVARCHAR(max)。

DECLARE @SQL NVARCHAR(MAX);
SELECT @SQL = CAST((

XML引擎用于连接字符串,这比使用普通的contattenation快,[text()]确保没有XML标记包围SQL代码。

    SELECT [text()] = REPLACE(REPLACE('

这是使用将被替换的占位符生成的SQL代码的模板。

        EXEC msdb.dbo.sp_send_dbmail 
            @profile_name=''eMail Profile'',
            @recipients=''{email}'',
            @subject=''Happy Birthday'',
            @body=''Happy BirthDay to {fullname}'',  
            @body_format = ''text'';
    '

替换占位符         &#39; {全名}&#39;,im.FullName)         &#39; {电子邮件}&#39;,cm.PersonalEmail) 将定义需要多少迭代的查询。

    FROM tblIndividualMst  im
        INNER JOIN tblContactMst cm 
            ON cm.ContactID = im.ContactID
    WHERE im.GroupID = 4673 
        AND im.DateOfBirth = CAST(GETDATE() AS DATE)

告诉SQL为此查询生成XML,但通过提供空字符串并使用[text()],我们确保结果中不包含任何标记。

    FOR XML PATH('')

将XML转换为NVARCHAR(最大值)

) AS NVARCHAR(max));

最后执行!

EXEC sp_executesql @SQL;