2012-10-28 48 views
2

我的DB中有2個表,一個包含有關客戶端(稱爲客戶端)的數據,另一個表包含clientID,Guid,AddedTime和IsValid(稱爲ClientsToUpdate)。JOIN的SQL塊更新

ClientID與客戶端表相關,Guid是唯一標識符,AddedTime是記錄添加到表的時間,如果此ClientID已更新,IsValid有點顯示。

我想要做的是更新它們的ID在ClientsToUpdate中的所有客戶端,問題是,ClientsToUpdate表包含超過80,000條記錄,並且我遇到了死鎖。

我雖然可以做,但是每次更新2000個客戶端,使用while循環或類似的東西。

我的存儲過程是這樣的:

UPDATE client SET LastLogin=GETDATE() 
FROM Clients client 
JOIN ClientsToUpdate ctu ON client.ID = ctu.ClientID; 

任何想法,我該怎麼辦呢?

回答

3
declare @done table (ClientID int primary key) 
while 1=1 
    begin 

    update top (2000) c 
    set  lastlogin = getdate() 
    output deleted.id into @done 
    from Clients c 
    join ClientsToUpdate ctu 
    on  c.id = ctu.ClientID 
    where not exists 
      (
      select * 
      from @done d 
      where d.ClientID = ctu.ClientID 
      ) 

    if @@rowcount = 0 
     break 
    end 

Example at SQL Fiddle.

+0

你能解釋你在這裏做了什麼? –

+0

基本上他正在更新查詢的前2000行,滿足where條件,直到所有80000行都被遍歷。他將更新行的id存儲到@done中以檢查(嵌套select *)。當@@ rowcount = 0時,這意味着什麼都沒有被更新,因此沒有任何東西需要更新現在是時候擺脫循環。 – Yatrix

+0

Andomar,應該是updated.ids而不是deleted.ids? – Yatrix

0

如果遇到死鎖,在大塊更新可能會減少錯誤(假設你小心管理您的交易並提交塊更新),但不解決死鎖原點。恕我直言,你應該調查鎖定問題,並找到爲什麼你有僵局