2012-09-08 39 views
1

我已經創建了一個系統,每天通過SMS向我們的客戶發送一些信息。因爲發送SMS的過程可能需要一段時間,這是由多個進程完成的,每個進程發送的SMS數量有限。當一個進程讀取多個pohne nubers記錄(可以說有1000個)發送短信。我想標記這1000條記錄,其他進程也不會讀取這些記錄。如何標記在mssql中讀取的記錄

Select Top(1000) ID, Number from Phones where isactive = 1 and isverified = 1 

我需要一些代碼,不會是這樣的:

現在我想這些記錄的列ReadTime更新爲getdate(),以確保

update Phones, set ReadTime = getdate() where(上面選擇),其他schduled過程將不會再讀他們(我設置日期時間標誌,而不是位標誌的原因是,某些短信發送可能會失敗,這種方式我可以理解哪些是很久以前閱讀,但沒有更新發送時間)

在發送短信之後標記它們(無論如何要寫入發送時間)都不會起作用,因爲處理髮送SMS的預定記錄將一次讀取所有1000條記錄,並且可能會有記錄被讀取其他進程,但還沒有爆發(因爲短信尚未發送)。

回答

3

你應該能夠做這樣的事情:

UPDATE Phones 
SET ReadTime = GetDate() 
WHERE ID IN (SELECT Top 1000 ID 
      FROM Phones 
      WHERE IsActive = 1 
       AND IsVerified = 1 
       AND ReadTime Is Null -- you will want to exclude any records already updated 
      ORDER BY ID) 

看到SQL Fiddle with Demo

+0

如何確保所選行與您更新的行相同? –

+0

@ t-clausen.dk實際上它會更新相同的記錄,如果添加了一個篩選器以包含它按預期工作的日期。 – Taryn

+0

您正在更新1000行,但這1000行並不總是與問題中選擇的行相同。因此,當您的查詢出錯時 –

1

願你可以添加一個額外的列這需要進程ID的ID表。 然後你可以在每個過程調用:

UPDATE Phones 
SET ReadTime = GetDate(), 
ProcessId = "Process0001" --or whatever the process ID is 
WHERE ID IN (SELECT Top 1000 ID FROM Phones WHERE IsActive = 1 AND IsVerified = 1 
       AND ProcessId IS NULL AND ReadTime IS NULL) 

然後調用的所有記錄你的進程ID。最後,您從表中刪除進程ID。

1

您可以一次選擇並輸出行。這將確保選中的行與更新的行相同,所選的答案不會執行此操作。

;with a 
as 
(
select top 1000 readtime, id, number from @phones 
where isactive = 1 and isverified = 1 
and readtime is null 
) 
update a 
set Readtime = getdate() 
output deleted.ID, deleted.Number 
+0

這條線'readtime Taryn

+0

@bluefeet是的,我誤解了關於讀取時間的部分,現在改變了這個部分。 –