23

我正在尝试开发邮件触发器。有人可以协助如何实现这一点,以便在用户插入记录时检查“速度”字段,以便当插入值超过 100 时,将邮件发送到指定地址。

4

1 回答 1

52

首先,您需要设置数据库邮件 - 如果您还没有这样做,这个问题可能会有所帮助:

然后你需要一个触发器:

CREATE TRIGGER dbo.whatever
ON dbo.wherever
FOR INSERT
AS
BEGIN
    SET NOCOUNT ON;

    IF EXISTS (SELECT 1 FROM inserted WHERE speed > 100)
    BEGIN
        EXEC msdb.dbo.sp_send_dbmail
          @recipients = 'whoever@yourcompany.com', 
          @profile_name = 'default',
          @subject = 'Someone was speeding', 
          @body = 'Yep, they sure were.';
    END
END
GO

现在,您可能会说您希望插入的数据实际包含在电子邮件中。您的第一个倾向是声明一些局部变量并从中分配它们inserted- 这不起作用,因为您的触发器可能响应多行插入。所以正确的做法是:

CREATE TRIGGER dbo.whatever
ON dbo.wherever
FOR INSERT
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @body NVARCHAR(MAX) = N'';

    SELECT @body += CHAR(13) + CHAR(10) + RTRIM(some_col) FROM inserted;

    IF EXISTS (SELECT 1 FROM inserted WHERE speed > 100)
    BEGIN
        EXEC msdb.dbo.sp_send_dbmail
          @recipients = 'whoever@yourcompany.com', 
          @profile_name = 'default',
          @subject = 'At least one person was speeding', 
          @body = @body;
    END
END
GO

总而言之,我不是从触发器发送电子邮件的忠实粉丝。尽管数据库邮件使用服务代理,因此是异步的,但我更倾向于填充队列表,并有一个后台线程来发送所有适当的电子邮件。关于此的两个三个好处是:

  1. 您可以最大限度地减少提交触发触发器的外部事务的潜在延迟 - 触发器中的逻辑越复杂,您执行该过程的速度就越慢。
  2. 由于在插入行的微秒内发送电子邮件可能不是必需的,因此您可以轻松地波动后台进程的时间 - 这避免了必须一整天都检查表的时间,而这种情况很少会发生永远不得不实际做任何事情。
  3. 正如@goodeye 指出的那样,将这个过程分开可以防止该过程的电子邮件部分中的错误干扰原始 DML(在他们的情况下,一个无效的参数sp_send_dbmail- 我无意中建议 - 阻止了插入)。
于 2012-05-25T13:45:28.393 回答