【问题标题】:Send email on trigger failure触发失败时发送电子邮件
【发布时间】:2012-08-14 09:41:05
【问题描述】:

我已成功配置并能够通过调用 msdb.dbo.sp_send_dbmail 存储过程在 SQL Server 2008 R2 上使用“数据库邮件”发送电子邮件。 我可以通过将它放在 try-catch 块中来捕获触发器中的查询失败。

但我需要做的是,当触发器无法执行查询时发送电子邮件。但是我不能在 catch 块中执行上面的存储过程。它给了我以下错误。

Msg 3930, Level 16, State 1, Procedure sp_send_dbmail, Line 64
The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction.
The statement has been terminated.

还有其他方法可以在触发失败时发送电子邮件吗? 或者如何解决这个问题?

【问题讨论】:

    标签: sql sql-server email triggers django-mssql


    【解决方案1】:

    触发器失败总是会导致事务回滚,因此它不能执行任何事务操作,例如调用sp_send_dbmail。一个技巧是利用自定义分析器跟踪事件,因为它们是在独立事务中发送的:

    create queue q;
    create service sq 
        on queue q
        ([http://schemas.microsoft.com/SQL/Notifications/PostEventNotification]);
    go
    
    create event notification trace_user_0
        on server 
        for TRC_USER_CONFIGURABLE
        to service N'sq', N'current database';
    go
    
    
    create procedure usp_sq
    as
    begin
    
        declare @dh uniqueidentifier, 
            @mt sysname, 
            @mb varbinary(max),
            @mx xml;
    
        begin transaction
    
        receive top(1) 
            @dh = conversation_handle,
            @mt = message_type_name,
            @mb = message_body
            from q;
    
        if @mt = N'http://schemas.microsoft.com/SQL/Notifications/EventNotification'
        begin
            set @mx = cast(@mb as xml);
    
            declare @eventText nvarchar(4000);
            select @eventText = @mx.value (N'(//EVENT_INSTANCE/TextData)[1]', N'nvarchar(4000)');
    
            exec sp_send_dbmail @subject = 'Error in trigger', @body = @eventText;
    
        end
        else if @mt in (
            N'http://schemas.microsoft.com/SQL/ServiceBroker/Error', 
            N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
        begin
            end conversation @dh;
        end
    
        commit
    
    end
    go
    
    alter queue q with activation (
        status = on,
        max_queue_readers = 1,
        execute as = 'owner',
        procedure_name = 'usp_sq');
    go
    
    create table MyTable (a int);
    go
    
    create trigger MyTrigger 
        on MyTable 
        after insert
    as
    begin try
        if rand() > 0.5
            raiserror (N'Something horrible happend in this trigger!', 16,1);
    end try
    begin catch
        declare @error_message nvarchar(256) = cast(error_message() as nvarchar(256));
        exec sp_trace_generateevent 82, @error_message;
    end catch
    go
    
    insert into MyTable (a) values (1);
    insert into MyTable (a) values (2);
    insert into MyTable (a) values (3);
    insert into MyTable (a) values (4);
    insert into MyTable (a) values (5);
    insert into MyTable (a) values (6);
    go
    

    【讨论】:

      猜你喜欢
      • 2017-12-08
      • 1970-01-01
      • 2017-02-09
      • 1970-01-01
      • 1970-01-01
      • 2016-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多