使用GETDATE触发问题

时间:2013-03-07 16:06:10

标签: sql-server-2008 triggers

我对这个完全感到难过。我有一个触发器,如果​​已经在表中插入了一条记录,它应该发送一封电子邮件,但是只有在最近20分钟左右没有插入的情况下才会发送。我已经将它缩小到它在插入查询中根本不喜欢GETDATE()的事实。

如果我更新我的存储过程以插入静态日期时间字符串,如“2013-03-07 09:53:54.12”,它将执行触发器并构建电子邮件正文,以便可以发送它。如果它在存储过程中使用GETDATE()或SYSDATETIME(),则在运行select命令后,body变量将为空。

我错过了什么吗?我之前没有找到任何发布的内容,但我很抱歉,这里已经发布并解决了这个问题。

我的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@domain.com",
            @subject="A Trial has been downloaded",
            @body=@body;
        INSERT INTO [DebugLog] (message) VALUES ('Mail sent');
        INSERT INTO [DebugLog] (message) VALUES (@body);
    END

2 个答案:

答案 0 :(得分:2)

基于Jason注意到的内容,我想说最好的办法是在关键字段或TrialRegistrations表上过滤NOT EXIST(...)子句。如果你这样做我认为你应该是直的。

...

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)

答案 1 :(得分:1)

所以看起来主要的是你将你的电子邮件基于主表中不存在行的那一行,其中该行与现在之间的日期差异小于20分钟且该行与插入的值共享相同的电子邮件和文件下载值。

所以,如果没有一行是真的,那么你只会收到一封电子邮件,但是你已经有一行是真的,那就是你刚插入的那一行。