2014-10-19 129 views
1

我有以下结构为什么INSERT触发器只发送一封电子邮件?

id | full_name | email 
------------------------------- 
1 | Ahmad  | [email protected] 
2 | Jack  | [email protected] 
3 | Mike  | [email protected] 
. . ..   .. 

等的表。

,我创建了以下触发发送电子邮件给谁的电子邮件刚刚插入(欢迎辞)的人:

create TRIGGER welcome_user ON users 
AFTER INSERT 
AS 
begin 
    declare @email varchar(100) 
    declare @full_name varchar(200) 
    declare @html varchar(4000) 

    select @email=i.email,@full_name=i.full_name from inserted i 


    set @html = 'Dear ' + @full_name + '<br><br> Welcome...' 

begin 
    exec msdb.dbo.sp_send_dbmail @profile_name = 'SQL Database Mail' 
    , @recipients = @email 
    , @copy_recipients = '[email protected]' 
    , @from_address = '[email protected]' 
    , @subject = 'Welcome' 
    , @body_format = 'HTML' 
    , @body = @html 

end 

end 
GO 

现在,上面的代码将工作,如果一个行被插入:

insert into users (id,full_name,email) values (900,'Jason','[email protected]') 

用户将收到一封电子邮件,我会被复制(因为我有机会获得[email protected]

但出现了一堆问题时一行插入全部,像这样做:

insert into users (id,full_name,email) 
    select id,full_name,email from temp_users where validated='Y' 

在上面的例子中,只有一个电子邮件发送(第一行被插入)。其他人被插入表中,但没有电子邮件发送给他们。一份副本都不会发送给我。

什么可能导致这种情况发生?

回答

1

触发器每个语句触发一次 - 不是每行一次。因此,inserted表在您的触发器中有多行 - 您只使用一行。你应该做的是将插入表中的记录复制到表变量中并循环。

正如@Aaron Bertrand所指出的 - 一个更好的解决方案是将触发器内的邮件依赖从一个存储过程中移除 - 一个是异步处理的。有了这个解决方案,您的触发器将填充充当队列的表。然后您将有一个读取此队列并发送电子邮件的过程。可以安排此过程(使用SQL代理或Service Broker),甚至可以手动运行。欲了解更多信息,请参阅herehere

+1

绝对正确。谢谢。 – Ahmad 2014-10-19 12:25:53

+0

不知道为什么您需要将行复制到表变量。您也可以使用基于集合的连接构建数据库邮件命令,而不需要任何显式循环。或者更好的办法是,[将行推入队列表并让一些后台进程选取要发送的邮件](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/12/bad-habits-to -kick-滥用-triggers.aspx)。 – 2014-10-19 14:21:43

+0

'SELECT @sql + = N'EXEC dbo.sp_send_dbmail @recipients = N'''+ iemail +''',...'FROM插入AS i;' – 2014-10-19 15:34:18

相关问题