使用 sp_send_dbmail 将电子邮件动态发送给多个收件人
Sending email dynamically to multiple recipients with message using sp_send_dbmail
其实我想给成员们送上生日祝福。我正在动态获取收件人列表。通过以下查询,我可以向成员发送问候。
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'
那么,如果@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 @Count = @Count + Count(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 @i int
set @i = 0
while @i <= @Count
begin
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'
end
那么,我该如何修改我的查询。感谢任何帮助,谢谢!!!
这里有一些观察...
- 您还没有在代码中的任何地方声明
@Count
。它需要声明为 INT
并设置为 0
- 在你的
WHILE LOOP
中你没有递增 @Count
所以这个循环是无限的
- 我会
@emails varchar(max)
以避免收件人列表被截断
据我所知,@recipList
毫无意义……您将其设置为 substring
,从 0 开始,一直到所有电子邮件的整个长度……这是同样的说法 set @recipList = @emails
- 您的 while 循环的构造不符合您希望它如何工作的逻辑。看起来您的意图是发送一封电子邮件,其中包含所有生日的名字。首先,我会在@body 中用逗号分隔这些名称。其次,您根本不需要循环。删除
WHILE
循环,因为您需要做的就是将电子邮件发送一次,发送到您已构建的 @recipList
列表,并连接 @bodycontent
。
综上所述...您的代码可以简化为下面应该有效的代码。
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
我个人反对在 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 引擎用于连接字符串,这比使用普通连接要快得多,[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'';
'
替换占位符
,'{全名}',im.FullName)
,'{电子邮件}',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(max)
) AS NVARCHAR(max));
最后执行!
EXEC sp_executesql @SQL;
其实我想给成员们送上生日祝福。我正在动态获取收件人列表。通过以下查询,我可以向成员发送问候。
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'
那么,如果@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 @Count = @Count + Count(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 @i int
set @i = 0
while @i <= @Count
begin
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'
end
那么,我该如何修改我的查询。感谢任何帮助,谢谢!!!
这里有一些观察...
- 您还没有在代码中的任何地方声明
@Count
。它需要声明为INT
并设置为0
- 在你的
WHILE LOOP
中你没有递增@Count
所以这个循环是无限的 - 我会
@emails varchar(max)
以避免收件人列表被截断
据我所知, @recipList
毫无意义……您将其设置为substring
,从 0 开始,一直到所有电子邮件的整个长度……这是同样的说法set @recipList = @emails
- 您的 while 循环的构造不符合您希望它如何工作的逻辑。看起来您的意图是发送一封电子邮件,其中包含所有生日的名字。首先,我会在@body 中用逗号分隔这些名称。其次,您根本不需要循环。删除
WHILE
循环,因为您需要做的就是将电子邮件发送一次,发送到您已构建的@recipList
列表,并连接@bodycontent
。
综上所述...您的代码可以简化为下面应该有效的代码。
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
我个人反对在 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 引擎用于连接字符串,这比使用普通连接要快得多,[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'';
'
替换占位符 ,'{全名}',im.FullName) ,'{电子邮件}',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(max)
) AS NVARCHAR(max));
最后执行!
EXEC sp_executesql @SQL;