T-SQL INSTEAD OF DELETE触发器在没有“挑衅”的情况下触发'

时间:2012-02-06 21:32:57

标签: sql-server-2008 tsql triggers

我有以下INSTEAD OF DELETE触发器,它会在回滚任何删除尝试时发送电子邮件。

ALTER TRIGGER tr_OnDel_Orders
ON  ORDERS 
INSTEAD OF DELETE
AS 
BEGIN

SET NOCOUNT ON;

declare @b varchar(5000)
Declare @OrderID BIGINT,

SELECT @OrderID  = OrderID
FROM deleted d

set @b = 'Someone attempted to delete the following order:' + CHAR(10);
set @b = @b + ' OrderID: ' + cast(@OrderID as varchar(30)) + CHAR(10);
set @b = @b + ' UserID: ' +  SYSTEM_USER

RAISERROR('Cannot delete order', 16, 1)
ROLLBACK TRAN

EXEC msdb.dbo.sp_send_dbmail @recipients = 'myemail@mycompany.com',
                         @body = @b,
                         @subject = 'Attempt to Delete an order' 


RETURN
END
GO

当我尝试从ORDERS表中删除订单时,这是有效的。但是,我无法理解为什么,这个触发器会定期用空体发送电子邮件。据我所知,没有明显的删除订单的尝试。还有什么可能导致这样的空白电子邮件?

2 个答案:

答案 0 :(得分:9)

此触发器处理多行删除,如果有人触发不删除任何行的删除语句,也不会向您发送无意义的电子邮件:

ALTER TRIGGER dbo.tr_OnDel_Orders
ON dbo.ORDERS 
INSTEAD OF DELETE
AS 
BEGIN
  IF EXISTS (SELECT 1 FROM deleted)
  BEGIN
    SET NOCOUNT ON;

    DECLARE @b VARCHAR(5000) = '';

    SELECT @b = @b + ',' + CONVERT(VARCHAR(12), OrderID)
        FROM deleted;

    SET @b = 'Someone attempted to delete the following orders:' 
        + CHAR(10) + @b + CHAR(10) + ' UserID: ' +  SYSTEM_USER;

    ROLLBACK TRANSACTION; -- should probably check @@TRANCOUNT first!

    EXEC msdb.dbo.sp_send_dbmail 
         @recipients = 'myemail@mycompany.com',
         @body = @b,
         @subject = 'Attempt to Delete an order';

    RAISERROR('Cannot delete order(s)', 16, 1);
  END

  RETURN;
END
GO

答案 1 :(得分:2)

关于触发器的最常见错误是它们通常是为每个已删除的记录工作一次而创建的。

但是如果使用一个DELETE语句删除了多个记录,则触发器应该能够像Aaron建议的那样处理所有已删除的记录。

在触发器中避免单值变量非常重要,开发人员应在触发器中构建基于集合的解决方案