【问题标题】:Send email based on each specific field that is updated根据更新的每个特定字段发送电子邮件
【发布时间】:2021-01-11 04:20:24
【问题描述】:

SQL Server 2017 对表的触发器 我有以下触发器正在运行,它可以工作。但是,我想根据更新的特定字段发送不同的电子邮件部分。我基本上想使用 SQL Server 发送邮件代码发送给不同用户的不同字段。我想知道是否有某种方法可以结合声明?我希望我问的是正确的!我的 SQL 就像 AT&T 的商业广告一样......就好了!因此,如果您可以提供帮助,请提供代码,如果这实际上可以完成。例如:

如果名字已更新,请发送/执行此操作:

      EXEC msdb.dbo.sp_send_dbmail
      @profile_name = 'Echo System',
      @recipients = 'sample1.com',
      @subject = 'Send email for sample1',
      @body = 'Please start a background check'

如果姓氏已更新,请发送/执行此操作

      EXEC msdb.dbo.sp_send_dbmail
      @profile_name = 'Echo System',
      @recipients = 'sample2.com',
      @subject = 'Send email for sample2',
      @body = 'Please start a background check'

发送/这样做是更新国籍。

      EXEC msdb.dbo.sp_send_dbmail
      @profile_name = 'Echo System',
      @recipients = 'sample3.com',
      @subject = 'Send email for sample3',
      @body = 'Please start a background check'
ALTER trigger [dbo].[updatePerson] on
[dbo].[person]
for update
as
 
      declare @personId int;
      declare @firstname varchar(50);
      declare @lastname varchar(50);
      declare @nationality varchar(100);
      declare @activity varchar(100);
 
      select @personId = s.personId from inserted s;
      select @firstname = s.firstname from inserted s;
      select @lastname = s.lastname from inserted s;
      select @nationality = s.nationality from inserted s;
 
      if update(firstname)
                  set @activity = 'Updated person firstname'
      if update(lastname)
                  set @activity = 'Updated person lastname'
      if update(nationality)
                  set @activity = 'Updated person nationality'
 
      
 
      EXEC msdb.dbo.sp_send_dbmail
      @profile_name = 'Echo System',
      @recipients = 'sampletriggernamen@gmail.com',
      @subject = ' follow the sampleaction you need to take. http://test.aspx',
      @body = 'Please start a background check'

【问题讨论】:

  • TRIGGER 发送电子邮件通常是个坏主意。例如,如果电子邮件发送失败,那么事务也会失败,因此不会更新行。然而,上面的TRIGGER 有更致命的缺陷;它假设 DML 操作只影响 1 行。 DML 语句会影响一行或多行,如果有更多行,上述语句将无法正常工作。理想地修复缺陷,然后将数据放入池表中;然后从那里发送电子邮件。更好的是,从应用层发送邮件;这才是这个逻辑应该存在的地方。
  • 此外,连接到 SMTP 服务器可能会涉及各种延迟和超时,这会减慢速度。
  • 您也从 "SQL Server 2017 Trigger on Table" 开始,但您的标签显示为 sql-server-2016。您实际使用的是哪个?
  • @Larnu, sql SERVER 2017。对不起那种类型。
  • 连接到 SQL Server 没有延迟。它实际上非常有效,没有任何延迟,但我需要向不同的用户发送通知,因为不同的用户拥有不同字段的更新。实际上,我通过搜索查看了其他一些系统,它们正在做非常相似的事情。

标签: .net sql-server tsql triggers sql-server-2017


【解决方案1】:

以下代码显示了如何通过循环遍历Inserted 伪表来处理多行。以及如何检测值的变化。

就每个更改类型发送不同的电子邮件而言,您已经有一个 IF 语句来分配您的 @activity,因此只需扩展它以设置要通过电子邮件发送的值。

但正如上面所评论的,在触发器中发送电子邮件是一个非常糟糕的主意。相反,您应该将要通过电子邮件发送的数据插入到队列表中,然后让另一个服务处理该队列。

ALTER trigger [dbo].[updatePerson] on
[dbo].[person]
for update
as
begin
    set nocount on;
     
    declare @personId int, @firstname varchar(50), @lastname varchar(50), @nationality varchar(100), @activity varchar(100)
      , @firstNameModified bit, @lastNameModified bit, @nationalityModified bit
      , @profile_name sysname, @recipients varchar(max), @subject nvarchar(255), @body nvarchar(max);

    select
        I.personId
        , convert(bit, case when coalesce(I.firstname,'') <> coalesce(D.firstname,'') then 1 else 0 end) firstnameModified
        , I.firstname
        , convert(bit, case when coalesce(I.lastname,'') <> coalesce(D.lastname,'') then 1 else 0 end) lastnameModified
        , I.lastname
        , convert(bit, case when coalesce(I.nationality,'') <> coalesce(D.nationality,'') then 1 else 0 end) nationalityModified
        , I.nationality
    into #updatePerson_temp
    from Inserted I
    -- Because its an 'update' trigger we can inner join
    inner join Deleted D on D.personId = I.personId
    where coalesce(I.firstname,'') <> coalesce(D.firstname,'')
    or coalesce(I.lastname,'') <> coalesce(D.lastname,'')
    or coalesce(I.nationality,'') <> coalesce(D.nationality,'');

    while exists (select 1 from #updatePerson_temp) begin
        -- Get first record to handle
        select top 1 @personId = personId
            , @firstnameModified = firstnameModified
            , @firstname = firstname
            , @lastnameModified = firstnameModified
            , @lastname = lastname
            , @nationalityModified = nationalityModified
            , @nationality = nationality
        from #updatePerson_temp;

        -- Following assumes only one change per record, modify to suit
        if @firstnameModified = 1 begin
            select @activity = 'Updated person firstname'
                , @profile_name = 'Echo System'
                , @recipients = 'sample1.com'
                , @subject = 'Send Email for Sample1'
                , @body = 'Please start a background check';
        end; else if @lastnameModified = 1 begin
            select @activity = 'Updated person lastname'
                , @profile_name = 'Echo System'
                , @recipients = 'sample2.com'
                , @subject = 'Send Email for Sample2'
                , @body = 'Please start a background check';
        end; else if @nationalityModified = 1 begin
            select @activity = 'Updated person nationality'
                , @profile_name = 'Echo System'
                , @recipients = 'sample3.com'
                , @subject = 'Send Email for Sample2'
                , @body = 'Please start a background check';
        end;

        -- Instead of sending the email here, queue it for later
        exec msdb.dbo.sp_send_dbmail
            @profile_name = @profile_name
            , @recipients = @recipients
            , @subject = @subject
            , @body = @body;

        -- Delete handled record
        delete from #updatePerson_temp where personId = @personId;
    end;
end;

【讨论】:

  • 感谢 Dale K。您的代码运行良好!我将查看表格中的值并让服务也这样做。现在我正在寻找和探索想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-19
  • 1970-01-01
  • 2012-01-30
  • 2013-12-02
  • 2022-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多