更新,然后选择更新的行?

问题描述

我有一个应用程序,该应用程序选择具有特定状态的行,然后开始处理这些行。但是,一些长时间运行的处理可能导致我程序的新实例启动,再次选择相同的行,因为它还没有时间更新状态。因此,我正在考虑选择我的行,然后将状态更新为其他内容,以便无法再次选择它们。我进行了一些搜索,并得到以下效果,但失败了。

  UPDATE table SET status = 5 WHERE status in 
  (SELECT TOP (10) * FROM table WHERE status = 1)

Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.

TLDR:是否可以同时选择和更新行? (顺序并不重要)

解决方法

您可以使用an output clauseupdate行,然后像对select一样返回它们。

对于仅更新前100行,一种安全的方法是使用cte首先选择相关行(我假设可以使用列id来对行进行排序):

with cte as (select top (100) * from mytable where status = 1 order by id)
update cte set status = 5 output inserted.*
,

您可以直接使用UPDATE语句。它将在该行上生成排他锁,其他并发事务无法读取该行。

More information on locks

排他锁::排他锁用于锁定由一个事务修改的数据,从而防止被另一事务修改 并发交易。您只能读取排他锁持有的数据 通过指定NOLOCK提示或使用读取的未提交隔离 水平。因为DML语句首先需要读取他们想要的数据 修改后,您将始终找到排他锁和共享锁 在相同的数据上。

UPDATE TOP(10) table 
SET status = 5 WHERE status =1