【问题标题】:Why does INSERT trigger only send one email?为什么 INSERT 触发器只发送一封电子邮件?
【发布时间】:2014-12-14 12:45:57
【问题描述】:

我有一个结构如下的表

id | full_name | email
-------------------------------
1  | Ahmad     | ahmad@some.com
2  | Jack      | jack@another.com
3  | Mike      | mike@yetanother.com
. .    ..          ..

等等。

我创建了以下触发器来向刚刚插入电子邮件的人发送电子邮件(作为欢迎消息):

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 = 'admin@mycompany.com' 
     ,  @from_address = 'admin@mycompany.com'
     ,  @subject =  'Welcome'
     ,  @body_format = 'HTML'
     ,  @body = @html

end

end
GO

现在如果插入一行,上面的代码就可以工作了:

insert into users (id,full_name,email) values (900,'Jason','jason@email.com')

用户会收到一封邮件,我会被复制(因为我可以访问admin@mycompany.com

但是当同时插入一堆行时会出现问题,执行如下操作:

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

在上面的示例中,仅发送了一封电子邮件(插入的第一行)。其他的被插入到表中,但没有电子邮件发送给他们。一份副本都没有寄给我。

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

【问题讨论】:

    标签: sql-server sql-server-2008 tsql email triggers


    【解决方案1】:

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

    正如@Aaron Bertrand 指出的那样——更好的解决方案是从触发器中删除邮件依赖项到存储过程——并异步处理。使用此解决方案,您的触发器将填充充当队列的表。然后,您将拥有一个读取此队列并发送电子邮件的过程。这个过程可以被安排(使用 SQL 代理或服务代理),甚至可以手动运行。有关详细信息,请参阅 herehere

    【讨论】:

    • 不确定为什么需要将行复制到表变量中。您还可以使用基于集合的连接潜在地构建数据库邮件命令,而无需任何显式循环。或者更好的是,push the rows to a queue table and let some background process pick up the mails to send
    • SELECT @sql += N'EXEC dbo.sp_send_dbmail @recipients = N''' + i.email + ''',...' FROM inserted AS i;
    • 我并不是说这一定是个好主意(因为有人本来可以将 anything 放入该电子邮件列中),我只是说您可以这样做没有循环。
    • 我发现串联比凌乱的循环或光标脚手架更容易编写、阅读和维护。我也喜欢巧克力,讨厌奶油奶酪。 YMMV。
    • @AaronBertrand 经过进一步研究,我认为更好的解决方案是从触发器中删除外部邮件依赖项 - 正如您在第一条评论中所建议的那样。我已将其添加到答案中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    • 2013-10-27
    • 1970-01-01
    相关资源
    最近更新 更多