2011-07-29 76 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