使用联接更新SQL数据块

使用联接更新SQL数据块,sql,stored-procedures,sql-update,Sql,Stored Procedures,Sql Update,我的数据库中有两个表,一个包含关于客户机的数据(称为客户机),另一个表包含clientID、Guid、AddedTime和IsValid(称为ClientsToUpdate) ClientID与clients表相关,Guid是唯一标识符,AddedTime是记录添加到表中的时间,IsValid是指示此ClientID是否更新的位 我想做的是更新ClientsToUpdate中的所有客户机,问题是,ClientsToUpdate表包含超过80000条记录,并且我遇到了死锁 我想我能做的是,使用wh

我的数据库中有两个表,一个包含关于客户机的数据(称为客户机),另一个表包含clientID、Guid、AddedTime和IsValid(称为ClientsToUpdate)

ClientID与clients表相关,Guid是唯一标识符,AddedTime是记录添加到表中的时间,IsValid是指示此ClientID是否更新的位

我想做的是更新ClientsToUpdate中的所有客户机,问题是,ClientsToUpdate表包含超过80000条记录,并且我遇到了死锁

我想我能做的是,使用while循环或类似的方法,一次更新2000个客户端

我的存储过程如下所示:

UPDATE client SET LastLogin=GETDATE() 
FROM Clients client
JOIN ClientsToUpdate ctu ON client.ID = ctu.ClientID;
知道我该怎么做吗

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

如果遇到死锁,分块更新可能会减少错误(假设您仔细管理事务并提交块更新),但不会解决死锁。IMHO您应该调查锁问题并找出死锁的原因

基本上,他正在更新查询中满足where条件的前2000行,直到遍历了所有80000行。他将更新行的ID存储到@done中以进行检查(嵌套的select*)。当@rowcount=0时,这意味着没有任何内容被更新,因此没有任何内容需要更新。是时候打破循环了。Andomar,这是应该更新的。ids而不是删除的。ids吗?@Yatrix:由于
id
列没有更改,您可以同时使用
删除的
(更新前的列值)和
插入的
(更新后的列值。)我不认为有一个
更新的
特殊表格。有趣。混乱。呵呵。