Sql server 2008 使用GETDATE时触发器出现问题
我在这件事上完全被难住了。我有一个触发器,如果记录被插入到表中,它应该发送一封电子邮件,但前提是在过去20分钟左右没有插入记录。我已经把范围缩小到一个事实,即它根本不喜欢insert查询中的GETDATE() 如果我更新存储过程以插入静态日期时间字符串,如“2013-03-07 09:53:54.12”,它将执行触发器并构造电子邮件正文,以便发送。如果在存储过程中使用GETDATE()或SYSDATETIME(),则body变量在运行select命令后将为空 我错过什么了吗?我还没有找到任何张贴在此之前,但我很抱歉,场景已经张贴和解决了这里 MVC项目中的insert命令如下所示:Sql server 2008 使用GETDATE时触发器出现问题,sql-server-2008,triggers,Sql Server 2008,Triggers,我在这件事上完全被难住了。我有一个触发器,如果记录被插入到表中,它应该发送一封电子邮件,但前提是在过去20分钟左右没有插入记录。我已经把范围缩小到一个事实,即它根本不喜欢insert查询中的GETDATE() 如果我更新存储过程以插入静态日期时间字符串,如“2013-03-07 09:53:54.12”,它将执行触发器并构造电子邮件正文,以便发送。如果在存储过程中使用GETDATE()或SYSDATETIME(),则body变量在运行select命令后将为空 我错过什么了吗?我还没有找到任何张贴
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());
我的存储过程如下所示:
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
因此,看起来最主要的是,您的电子邮件基于一个WHERE NOT existed,在主表中有一行,该行与当前的日期差小于20分钟,并且该行与插入值共享相同的email和filedownload值
因此,如果没有一行是真的,那么你只会收到一封电子邮件,但是你已经有了一行是真的,也就是你刚才插入的那一行。根据Jason注意到的,我认为最好的办法是在一个键字段或
TrialRegistrations
表上过滤你的NOT EXIST(…)子句。如果你那样做的话,我认为你应该是正直的
首先,不要在触发器中发送电子邮件。您应该将要发送电子邮件的记录发送到pable,然后每隔5分钟左右运行一次作业以发送电子邮件。如果电子邮件服务器宕机,您不想中断插入。@HLGEM这不正是sp_send_Dmail在SQL server 2008中的行为吗?DownloadTime列是什么数据类型?我的印象是sp_send_Dmail已经这样做了。不是吗?另外,DateTime2是DownloadTime的数据类型。我认为这是正确的。20>DATEDIFF(分钟,o.DownloadTime,GETDATE())对我来说就像差不到20分钟;所以他说他不想为匹配时间少于20分钟的条目发送邮件。@MojoFilter如果不是因为他刚才插入的行,这也没关系。我可能弄错了,但我很确定这一行被认为是在主表中。他可以改为对datediff大于20的数据进行存在检查,这样他只会在这是真的情况下发送电子邮件。哦,是的。我以为这是一个而不是插入触发器。我想那会是个问题。不过,我得到的印象是,他用这个来限制发送的电子邮件。所以,检查是否有一个旧的是不够的。这是非常有帮助的。您可能是对的,插入的记录很可能是我查询的表的一部分。我没有意识到这一点。