2012-08-14 153 views
0

我已成功配置並能夠通過調用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. 

是否有其他方式發送觸發失敗的電子郵件? 或者如何解決這個問題?

回答

0

觸發失敗將始終導致事務回滾,因此無法執行任何事務操作,如調用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