2011-07-29 48 views
0

所以我有这个存储过程来插入一条消息到我的数据库。我想阻止用户在短时间内发布重复邮件,无论是意外还是故意(无论是延迟连接还是垃圾邮件发送者)。防止在SQL Server中的重复记录

这是插入语句是什么样子:

IF NOT EXISTS (SELECT * FROM tblMessages WHERE message = @message and ip = @ip and datediff(minute,timestamp, getdate()) < 10) 
    BEGIN 
     INSERT INTO tblMessages (ip, message, votes, latitude, longitude, location, timestamp, flags, deleted, username, parentId) 
     VALUES (@ip, @message, 0, @latitude, @longitude, @location, GETDATE(), 0, 0, @username, @parentId) 
    END 

你可以看到我检查,看看是否同一用户已张贴在10分钟内相同的消息,如果没有,我将它张贴。我仍然看到昨天有一个重复。当我检查数据库中两条消息的时间戳时,它们完全一样,直到第二条,所以我猜测每次插入时运行这个“存在”检查时,都返回空,所以它们都插入正确(在基本上相同的时间)。

什么是我可以防止这种情况发生的正确方法?

回答

1

我想你需要一个触发

唯一约束/索引是没有足够的智慧来处理岗位之间的10个微小间隙给定消息和IP。

CREATE TRIGGER TRG_tblMessages_I FRO INSERT 
AS 
SET NOCOUNT ON; 

IF EXISTS (SELECT * 
     FROM tblMessages M 
      JOIN INSERTED I ON M.message = I.message and M.ip = I.ip 
     WHERE 
      datediff(minute, M.timestamp, I.timestamp) < 10) 
BEGIN 
    RAISERRROR ('blah', 16, 1) 
    ROLLBACK TRAN 
END 

编辑:您需要一个额外的条件不理你刚刚插入(例如,使用代理键)在同一行

+0

这会识别一条消息在同一时间发布? – slandau

+0

@slandau:是的,会的。看到我的更新请 – gbn

+0

我认为这是最好的解决方案。 - 我不需要提出错误的权利?我可以平静地回滚? – slandau

0

添加唯一约束表中,以绝对防止它发生

ALTER TABLE tblMessages ADD CONSTRAINT uq_tblMessages UNIQUE (message,ip,timestamp) 
+0

时间戳可以通过10分钟的不同。 – ozczecho

+1

但想法是对的。 –

+0

这个想法是对的吗?建议的解决方案不适用于OP发布的场景。 – ozczecho

0

我认为,最简单的方法是使用触发器来检查邮件的发件人和身体在表中已有的记录。

,或者德里克说,你可以使用约束,但其他条件:

ALTER TABLE tblMessages ADD CONSTRAINT uq_tblMessages UNIQUE (message,ip,username, parentId) 

但约束则会产生异常(你将需要处理的话)。

1

其实Derek Kromm并不遥远;基本上你确实需要一个唯一的约束,你只需要一个列的范围。

您可以将其表示为filtered index,它强制所需列的唯一性,但使用过滤器在10分钟范围内匹配时间戳。

CREATE NONCLUSTERED INDEX IX_UNC_tblMessages 
ON tblMessages (message, ip, timestamp) 
WHERE datediff(minute, timestamp, getdate()) < 10) 

在唯一约束和其保持唯一性(​​3210)过滤的折射率之间的差:

有创造一个独特 约束和创建独立的唯一索引之间没有显著差异约束。 数据验证以相同方式进行,查询优化器 不区分由约束创建的唯一索引或手动创建的 。但是,当数据完整性为目标时,您应该在该列上创建唯一或主键约束。通过 这样做,索引的目标将是明确的。

这个我不确定的唯一方面是使用getdate()。我不确定将会对索引和性能产生什么影响 - 您需要自己测试一下。

+0

+1伟大的解决方案。 – ozczecho

+1

除了结果创建索引是'消息10735,级别15,状态1,行6 表'tblMessages'上过滤索引'IX_UNC_tblMessages'的WHERE子句不正确。查看文档,它看起来不允许函数在哪里子句创建一个筛选索引时:http://msdn.microsoft.com/en-us/library/ms188783.aspx –

+0

是啊,这似乎是一个很好的解决方案,但我也得到这个错误=/ – slandau