1

Microsoft SQL Server で、日付が連続して変更された場合にメールを送信する更新トリガーを作成しました。

これに似ています:

IF UPDATE(ColumnName)
    BEGIN
        DECLARE @columnVal AS DATETIME

        SELECT 
            @columnVal = i.columnName
        FROM 
            inserted i JOIN deleted d on i.RowId= d.RowId;

        EXEC msdb.dbo.sp_send_dbmail
                @profile_name = 'me',
                @recipients = 'me@company.com',
                @body = 'blah blah datechange',
                @body_format = 'HTML',
                @subject = 'subject';
END

しばらくはうまくいきました。
次に、バッチ更新に切り替え、日付が複数の行で変更された場合、最初の行の電子メールのみが送信されます。変更をロールスルーするようにカーソルを設定しようとしましたが、次のように機能しません。

DECLARE @columnVal AS DATETIME

DECLARE cur CURSOR LOCAL READ_ONLY FAST_FORWARD FOR
    SELECT
        i.ColumnName
    FROM 
    inserted i JOIN deleted d on i.RowId= d.RowId;

OPEN cur

FETCH NEXT FROM cur INTO @columnVal

WHILE @@FETCH_STATUS = 0
BEGIN
   IF UPDATE(ColumnName)
   BEGIN
        EXEC msdb.dbo.sp_send_dbmail
                @profile_name = 'me',
                @recipients = 'me@company.com',
                @body = 'blah blah datechange',
                @body_format = 'HTML',
                @subject = 'subject';
    END

    FETCH NEXT FROM cur INTO @columnVal
END

CLOSE cur
DEALLOCATE cur

このタスクを達成する方法についてのアイデアはありますか? Update(ColumnName) 関数は、カーソル内にネストされていても適切に機能しますか (その列がその行に対して更新されたかどうかを実際に教えてくれますか?)

4

1 に答える 1

2

トリガー内のカーソルは非常に悪い考えです。

トリガーは非常に無駄のないものにする必要があります。多くの作業を行うべきではありません。誰に電子メールを送信する必要があるかを「メモする」ことだけをお勧めしますが、電子メールの実際の送信は、トリガーの一部ではない別のたとえば SQL Server エージェント ジョブに任せます。

トリガーは頻繁に、そして多くの場合予期せずに起動されます。処理負荷のログをトリガーに入れないようにしてください。特に、カーソルのようなパフォーマンスキラーではありません!

興味のある行を見つけるには、次のWHEREような句を使用できます。

WHERE inserted.ColumnName <> deleted.ColumnName

UPDATEトリガーのコンテキストでは、これは の新しい値がColumnName古い値と異なることを意味します --> この列は更新されました。

于 2013-10-23T16:10:13.770 に答える