Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Tsql 防止SQL Server中的重复记录_Tsql_Sql Server 2008 - Fatal编程技术网

Tsql 防止SQL Server中的重复记录

Tsql 防止SQL Server中的重复记录,tsql,sql-server-2008,Tsql,Sql Server 2008,因此,我有一个存储过程将消息插入数据库。我想防止用户在短时间内发布重复的消息,无论是出于意外还是出于延迟连接或垃圾邮件发送者的目的 这是insert语句的外观: IF NOT EXISTS (SELECT * FROM tblMessages WHERE message = @message and ip = @ip and datediff(minute,timestamp, getdate()) < 10) BEGIN INSERT INTO tblMessag

因此,我有一个存储过程将消息插入数据库。我想防止用户在短时间内发布重复的消息,无论是出于意外还是出于延迟连接或垃圾邮件发送者的目的

这是insert语句的外观:

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分钟内发布了相同的消息,如果没有,我就发布它。我昨天还看到一个傻瓜。当我检查数据库中两条消息的时间戳时,它们完全相同,一直到第二条,所以我猜每次插入时都会执行“存在”检查,结果都是空的,所以它们都在基本相同的时间插入


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

向表中添加一个唯一的约束,以绝对防止这种情况发生

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

我认为,最简单的方法是使用触发器检查表中现有记录中的发件人和消息体

或者,正如Derek所说,您可以使用约束,但有另一个条件:

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

但约束将生成异常,您需要处理它。

事实上,德里克·克罗姆已经不远了;实际上,您确实需要一个唯一的约束,您只需要其中一列的范围

您可以将其表示为,它在您想要的列上强制执行唯一性,但使用过滤器匹配10分钟范围内的时间戳

CREATE NONCLUSTERED INDEX IX_UNC_tblMessages
ON tblMessages (message, ip, timestamp)
WHERE datediff(minute, timestamp, getdate()) < 10)
关于唯一约束和保持唯一性的过滤索引之间的差异:

创建一个独特的 约束并创建独立于约束的唯一索引。 数据验证的方式与查询优化器相同 不区分由约束或约束创建的唯一索引 手动创建。但是,您应该创建一个唯一的或主键 以数据完整性为目标时对列的约束。通过 这样做,索引的目标将是明确的


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

我想您需要一个触发器

唯一的约束/索引不够聪明,无法处理给定消息和ip的帖子之间10分钟的间隔

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

编辑:您需要一个额外的条件来忽略刚才插入的同一行,例如使用代理键

时间戳可以相差10分钟。这个想法如何正确?建议的解决方案不适用于OP发布的场景。@ozczecho从概念上讲,使用约束强制唯一性的想法是正确的,只是唯一约束的这种特定构造在我的回答中不太正确,除了结果创建索引是Msg 10735,级别15,状态1,第6行“tblMessages”表中过滤索引“IX_UNC_tblMessages”的WHERE子句不正确。查看文档,在创建过滤索引时,where子句中似乎不允许使用函数:是的,这似乎是一个很好的解决方案,但我也遇到了这个错误=/这会识别在同一时间发布的消息吗?我认为这是最好的解决方案。-我不需要提出错误,对吗?我可以安静地后退吗?@slandau:你可以安静地后退,是的。