0

我有四张桌子:

活动:

ActivityID(PK)    ActivityName      CustomerID(FK)  UserId(FK)
1                Lead Gen 1st           50         U1
2                Lead Gen 2nd           60         U2

顾客:

CustomerID(PK)   CustomerNumber  CustomerName
50                  C0150          cust50 ltd
60                  C0160          cust60 ltd

用户:

UserID(PK)  UserName     Email        
U1           Mr. X      X@cat.com        
U2           Mr. Y      Y@cat.com 

用户活动:

UserActivityID(PK)  UserID(FK)     ActivityID(FK) 
888                   U1             1
889                   U2             2

Activity如果表(SQL Server 2008-R2)中发生任何插入,我想向与活动相关的用户(即 ActivityId:1)发送一封电子邮件(即 Email:X@cat.com )。

电子邮件正文应包含ActivityIdActivityName和。CustomerNumberCustomerName

触发器必须执行上述操作,结果在电子邮件中应该是这样的:

ActivityID:1, ActivityName:Lead Gen 1st created for  CustomerNumber: C0150 & CustomerName: cust50 ltd

这是我的代码:

CREATE TRIGGER [dbo].[Activity_Insert_Mail_Notification]
  ON [dbo].[Activity]
AFTER INSERT
AS
BEGIN

  DECLARE @ActivityID varchar(2000)
  DECLARE @ActivityName varchar (2000)

  Select @ActivityID=inserted.ActivityID,@ActivityName=inserted.ActivityName 
    From inserted


  DECLARE @CustomerNo varchar(2000)
  DECLARE @CustomerName varchar(2000)

  Select @CustomerNo = B.[CustomerNumber]
        ,@CustomerName= B.[CustomerName]
    from [dbo].[Activity] A 
    inner join [dbo].[Customer] B 
      on A.[CustomerID]=B.[CustomerID]

  DECLARE @email VARCHAR(2000)

  SELECT  @email = RTRIM(U.[Email]) + ';'
    FROM [dbo].[Activity] A
      left join [dbo].[UserActivity] UA   
        inner join [dbo].[User] U 
          on UA.[UserID]=U.[UserID]
        on A.[ActivityID]=UA.[ActivityID]
    WHERE U.[Email]<> ''

  DECLARE @content varchar (2000)
    = 'ActivityID:' + @ActivityId + ' ' 
    + ',ActivityName:' + @ActivityName + ' ' 
    + 'has been created for' + 'CustomerNumber: ' + @CustomerNo
    + ' ' + '&CustomerName: ' + @CustomerName

  EXEC msdb.dbo.sp_send_dbmail
       @profile_name = 'LEADNOTIFY'
      ,@recipients = @email
      ,@subject = 'New Lead Found'
      ,@body = @content
      ,@importance ='HIGH'

END

问题出在我的代码中,我无法正确地从各个表中获取客户数据和电子邮件。

4

1 回答 1

0

我在下面编写了一些代码,它将遍历所有受影响的行并为每个行发送一封电子邮件。

但是,在您阅读之前,我强烈建议(正如@HABO 评论的那样)使用不同的方法。触发器适用于某些任务,但在使用触发器时要记住 2 个关键事项:

  1. 确保任何开发系统的人都清楚有触发器 - 作为开发人员,没有什么比在看似简单的 CRUD 操作上神奇地发生的事情更糟糕的了。
  2. 尽可能快地执行您在触发器中所做的任何事情,因为您持有的锁不仅会影响当前会话,而且很容易影响其他用户。因此,理想情况下,您希望执行基于集合的操作,而不是 RBAR(Row By Agonizing Row)操作。

在触发器内发送电子邮件是一件可怕的事情,因为被迫等待 SMTP 服务器响应的情况并不少见。如果您希望触发电子邮件,更好的方法是使用触发器将电子邮件数据插入到排队表中,然后在其他地方提供服务,将这些电子邮件从队列中取出并发送。

除了以下代码之外,所有这些都显示了当您想要执行 RBAR 操作时处理Inserted伪表的一种方法。因为在 SQL Server 中,Inserted伪表(和Deleted伪表)将包含受操作影响的行数,即 0-N。此外,我希望加入您的表格以正确获取所需的信息。

CREATE TRIGGER [dbo].[Activity_Insert_Mail_Notification]
  ON [dbo].[Activity]
AFTER INSERT
AS
BEGIN
  SET NOCOUNT ON;

  DECLARE @ActivityID VARCHAR(2000), @ActivityName VARCHAR(2000), @CustomerNo VARCHAR(2000), @CustomerName VARCHAR(2000), @Email VARCHAR(2000), @Content VARCHAR(2000);

  -- Get all the relevant information into a temp table
  SELECT ActivityID, ActivityName, C.CustomerNumber, C.CustomerName, RTRIM(U.[Email]) + ';' Email, CONVERT(BIT, 0) Handled
  INTO #ActivityTriggerTemp
  FROM Inserted I
  INNER JOIN Customer C on C.CustomerID = I.CustomerID
  INNER JOIN UserActivity UA on UA.ActivityID = I.ActivityID
  INNER JOIN [USER] U on U.UserID = UA.UserID;

  -- Loop through the temp table sending an email for each row, then setting the row as 'handled' to avoid sending it again.
  WHILE EXISTS (SELECT 1 FROM #ActivityTriggerTemp WHERE Handled = 0) BEGIN
    SELECT TOP 1 @ActivityID = ActivityID, @ActivityName = ActivityName, @CustomerNumber = CustomerNumber, @CustomerName = CustomerName, @Email = Email
    FROM #ActivityTriggerTemp
    WHERE Handled = 0;

    -- Build the body of the email
    set @Content = 'ActivityID:' + @ActivityId + ' ' 
      + ',ActivityName:' + @ActivityName + ' ' 
      + 'has been created for' + 'CustomerNumber: ' + @CustomerNo
      + ' ' + '&CustomerName: ' + @CustomerName;

    -- Send the email
    EXEC msdb.dbo.sp_send_dbmail
      @profile_name = 'LEADNOTIFY'
      , @recipients = @Email
      , @subject = 'New Lead Found'
      , @body = @Content
      , @importance ='HIGH';

    UPDATE #ActivityTriggerTemp SET
      Handled = 1
    WHERE ActivityID = @ActivityID AND ActivityName = @ActivityName AND CustomerNumber = @CustomerNumber AND CustomerName = @CustomerName AND Email = @Email;
  END;
END
于 2020-06-15T21:58:31.000 回答