2016-02-12 44 views
1

我正在使用SQL Server,我需要一種方法來強制我的數據庫在3分鐘內只允許一個特定記錄的插入。如何強制SQL Server只允許每3分鐘插入一條記錄

例如,如果我插入一個電話號碼爲3053333333的記錄,我需要一種方法來強制3分鐘後不再輸入相同的電話號碼。

我需要在數據庫級別執行此操作。任何幫助將不勝感激。

+0

難道你不能限制插入是如何完成的嗎? – Carcigenicate

+1

首先想到的是插入觸發器。 –

+0

爲什麼需要在數據庫級別?在數據庫抽象級別很容易做到。 – Eborbob

回答

0

插入時在記錄上存儲時間戳。

在每次插入時,檢查當前時間與同一電話號碼的最後一次時間戳是否至少3分鐘。

如果您正在通過存儲過程進行插入,請在那裏執行檢查。否則你將不得不這樣做在觸發器

2

不完全是你要求的,但它應該是一個足夠好的近似值。 這種方法的好處是易於實現並且高效。不需要觸發器。

添加int列將被用默認值使用此表達式自動填充該表:

datediff(minute,'2001-01-01',getdate())/(3) 

該表達式計算,因爲一些參考日期多少分鐘(除以3)已經過去(2001 -01-01)。

然後在PhoneNumber和這個PhoneTimestamp列上添加唯一索引。

CREATE TABLE [dbo].[TestTable](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [PhoneNumber] [varchar](50) NOT NULL, 
    [PhoneTimestamp] [int] NOT NULL CONSTRAINT [DF_TestTable_PhoneTimestamp] 
    DEFAULT (datediff(minute,'2001-01-01',getdate())/(3)), 
CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)) 
GO 

CREATE UNIQUE NONCLUSTERED INDEX [IX_PhoneNumber] ON [dbo].[TestTable] 
(
    [PhoneNumber] ASC, 
    [PhoneTimestamp] ASC 
) 
GO 

插入值表中不設置PhoneTimestamp明確,讓默認表情工作:

INSERT INTO [dbo].[TestTable] ([PhoneNumber]) VALUES 
('124'); 

第一INSERT將正常工作,但如果你試圖在同一3再次運行 - 分爲「時隙」它將失敗與消息:

Msg 2601, Level 14, State 1, Line 1 
Cannot insert duplicate key row in object 'dbo.TestTable' with unique index 
'IX_PhoneNumber'. The duplicate key value is (124, 2649888). 
The statement has been terminated. 

它是一個近似值,因爲你可以插入小於3分鐘的間隔兩行。如果插入第一行,例如,在10:02:58,第二行插入10:03:02,它將被接受。但是,如果您在10:03:02處插入一行,則只有在10:06:00之後纔會接受下一行。

1

只要在最近三分鐘內沒有記錄就插入。

DECLARE @ThreeMinutesAgo datetime2 = 
    DATEDIFF(minute, -3, getdate()) 

IF NOT EXISTS (
    SELECT * FROM PhoneRecords 
    WHERE PhoneNumber = @PhoneNumber 
    AND TimeStamp > @ThreeMinutesAgo) 
    INSERT INTO PhoneRecords 
    (PhoneNumber, TimeStamp, MoreStuff) 
    VALUES 
    (@PhoneNumber, getdate(), @MoreStuff) 

編輯解決以下弗拉基米爾的評論:

我會去這個使用第二表******中國作爲重點,跟蹤最新記錄。

CREATE TABLE PhoneNumbers (
    PhoneNumber varchar(50) NOT NULL PRIMARY KEY, 
    LastTimeStamp datetime2 
) 

PhoneNumber將是PhoneRecords表中的外鍵。要添加一個新的記錄:

DECLARE @Timestamp datetime2 = getdate() 
DECLARE @ThreeMinutesAgo datetime2 = 
     DATEDIFF(minute, -3, @Timestamp) 

UPDATE PhoneNumbers 
    SET LastTimeStamp = @TimeStamp 
    WHERE PhoneNumber = @PhoneNumber AND LastTimeStamp < @ThreeMinutesAgo 

,只有當時間戳在3分鐘內舊的工作 - 並且注意,如果另一個進程正在更新記錄,我必須等待它被解鎖試試我的更新。所以,如果我做了更新,

IF @@ROWCOUNT = 1 
    INSERT INTO PhoneRecords 
     (PhoneNumber, TimeStamp, MoreStuff) 
     VALUES 
     (@PhoneNumber, @Timestamp, @MoreStuff) 

你會希望把他們在一個事務,還要檢查需要插入在PHONENUMBERS表中的第一次的電話號碼。

+0

當多次嘗試同時插入相同的值時,如何使它可靠地工作?我提到OP在這個問題的評論中所寫的關切。 –

+0

在上面添加了一個編輯來解決這個問題@VladimirBaranov – RocketCity

+0

@VladimirBaranov:我喜歡你的方法,結果非常簡潔:TRY - 插入 - CATCH - 什麼也不做。 我的問題是,我試圖在預期條件下不使用「CATCH」。有沒有性能方面的考慮?如果這種情況發生的時間不是很少,但是大概會失敗呢?我想知道是否有任何性能損失試圖插入一個壞的外鍵,相比之下首先檢查一個有效的。這可能取決於您嘗試添加不需要的記錄的頻率與有效記錄的頻率。 – RocketCity

相關問題