2013-03-07 2 views
2

Я полностью в тупике. У меня есть триггер, который должен отправить электронное письмо, если запись была вставлена ​​в таблицу, но только если она не была вставлена ​​за последние 20 минут или около того. Я сузил его до того, что он просто не похож на GETDATE() в запросе вставки.Проблема с триггером с использованием GETDATE

Если я обновляю хранимую процедуру, чтобы вставить статическую дату, например «2013-03-07 09: 53: 54.12», она выполнит триггер и построит тело электронной почты, чтобы оно могло быть отправлено. Если в хранимой процедуре используется GETDATE() или SYSDATETIME(), переменная body будет пустой после запуска команды select.

Я что-то упустил? Я не могу найти ничего, что было опубликовано ранее, но я извиняюсь, что сценарий уже опубликован и разрешен здесь.

Моя команда вставки в моем проекте MVC выглядит следующим образом:

SqlConnection conn = new SqlConnection(); 
     conn.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["RegistrationEntriesConnectionString"].ToString(); 

     SqlCommand command = new SqlCommand("RegisterCustomerDownload", conn); 
     command.CommandType = System.Data.CommandType.StoredProcedure; 

     command.Parameters.AddWithValue("@Email", userEmail); 
     command.Parameters.AddWithValue("FileDownloaded", "Product Name Here"); 

     try 
     { 
      //Open connection and try to execute the command 
      conn.Open(); 
      command.ExecuteNonQuery(); 

      conn.Close(); 
     } 
     catch (Exception ex) 
     { 
      //do something 
     } 

Моя хранимая процедура выглядит следующим образом:

SET NOCOUNT ON; 

INSERT INTO TrialDownloads(Email, FileDownloaded, DownloadTime) 
VALUES(@Email, @FileDownloaded, GETDATE()); 

Оттуда, у меня есть триггер (для вставки), чем посылает электронной почты, если последняя соответствующая запись была вставлена ​​дольше, чем 20 минут назад:

SET NOCOUNT ON; 

DECLARE @body NVARCHAR(MAX) = N''; 

--For debugging purposes 
INSERT INTO [DebugLog] (message) VALUES ('Entered SendTrialDownloadEmail'); 

SELECT @body += 'A trial has been downloaded:' + 
     CHAR(13) + CHAR(10)+ 'Email Address: ' + Email + 
     CHAR(13) + CHAR(10)+ 'Product Downloaded ' + FileDownloaded + 
     CHAR(13) + CHAR(10)+ 'Date Downloaded: ' + CONVERT(NVARCHAR, DownloadTime) 
    FROM [inserted] i 
     WHERE NOT EXISTS (SELECT * FROM [dbo].[TrialDownloads] o 
     WHERE 20 > DATEDIFF(minute, o.DownloadTime, GETDATE()) 
      AND i.Email = o.Email 
      AND i.FileDownloaded = o.FileDownloaded); 

--For debugging purposes 
INSERT INTO [DebugLog] (message) VALUES ('Before IF block'); 
INSERT INTO [DebugLog] (message) VALUES (@body); 
DECLARE @insertCount NVARCHAR(MAX); 
SELECT @insertCount = CONVERT(nvarchar, COUNT(*)) FROM inserted 
INSERT INTO DebugLog (message) VALUES (@insertCount); 


IF NOT @body = N'' 
    BEGIN 
     EXEC msdb.dbo.sp_send_dbmail 
      @profile_name="NoReplyProfile", 
      @recipients="[email protected]", 
      @subject="A Trial has been downloaded", 
      @[email protected]; 
     INSERT INTO [DebugLog] (message) VALUES ('Mail sent'); 
     INSERT INTO [DebugLog] (message) VALUES (@body); 
    END 
+0

Во-первых, никогда не отправить по электронной почте в качестве триггера. Вы отправляете записи, чтобы отправлять электронные письма в папку, а затем запускать работу каждые 5 минут, чтобы отправить электронные письма. Вы не хотите разрывать вставки, если сервер электронной почты идет вниз. – HLGEM

+0

@HLGEM Не так ли работает sp_send_dbmail в SQL Server 2008? – MojoFilter

+0

Какой тип данных является столбцом DownloadTime? – HLGEM

ответ

2

Основываясь на том, что заметил Джейсон, я бы сказал, что лучше всего будет также фильтровать ваше предложение NOT EXIST (...) в поле ключа или в таблице TrialRegistrations. Я думаю, вы должны быть прямыми, если вы это сделаете.

...

WHERE NOT EXISTS (SELECT * FROM [dbo].[TrialDownloads] o 
     WHERE 20 > DATEDIFF(minute, o.DownloadTime, GETDATE()) 
      AND i.Email = o.Email 
      AND i.FileDownloaded = o.FileDownloaded 
      AND NOT i.Id = o.Id) 
+0

Я добавил это, и он работал по назначению. Благодарю. –

1

Так выглядит Главное, что вы основываете свою электронную почту на ГДЕ НЕ СУЩЕСТВУЕТ строку в вашей основной таблице, где разница в дате между этой строкой и сейчас составляет МЕНЬШЕ, чем 20 минут, и эта строка разделяет один и тот же адрес электронной почты и заполняет загруженные значения как вставленное значение.

Значит, вы получите электронное письмо, если нет строки, где это правда, но у вас уже есть строка, где это правда, только что вставленная строка.

+0

Извините, искал этот ответ сначала, отредактированный для ясности. –

+0

Я думаю, что это правильно. 20> DATEDIFF (минута, o.DownloadTime, GETDATE()) читает мне, как разница составляет менее 20 минут; поэтому он говорит, что не хочет отправлять почту для записей, имеющих совпадение менее 20 минут. – MojoFilter

+0

@MojoFilter Что было бы в порядке, если бы не строка, которую он только что вставил. Я мог ошибаться, но я уверен, что для этой цели считается, что эта строка находится в главной таблице. Он мог вместо этого выполнить проверку EXISTS для датированного более 20, чтобы он отправлял электронные письма только в том случае, если это правда. –

Смежные вопросы