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.

トリガーの失敗時に電子メールを送信する他の方法はありますか? または、これを修正する方法は?

4

1 に答える 1

0

トリガーが失敗すると、常にトランザクションのロールバックが発生するため、呼び出しなどのトランザクション操作を実行できませんsp_send_dbmail。カスタム プロファイラー トレース イベントはスタンドアロン トランザクションで送信されるため、これらを活用するのが 1 つの秘訣です。

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
于 2012-08-14T11:35:10.377 に答える