Как выбрать запись из базы данных и обновить ее в атомарном запросе - PullRequest
11 голосов
/ 20 апреля 2011

У меня есть несколько записей в таблице со столбцом Status, и я хочу выбрать одну запись, где Status = Pending и в том же атомарном запросе пометить ее как Status = InProcess. Какой лучший способ сделать это?

Это необходимо, поскольку одновременно могут выполняться несколько запросов, пытающихся обработать эти записи, и я не хочу, чтобы два потока принимали одну и ту же запись для обработки.

Ответы [ 4 ]

15 голосов
/ 20 апреля 2011

Вы можете использовать предложение OUTPUT:

UPDATE [table]
SET Status = 'InProcess'
OUTPUT deleted.*
WHERE Status = 'Pending'

Здесь вы можете использовать вставленное имя таблицы, если вы хотите получить строку с новым статусом или удаленное в старом возрасте.

6 голосов
/ 20 апреля 2011

Вот статья о Использование таблиц в качестве очередей .

С этой таблицей create table T (ID int identity, Status varchar(15)) Нечто подобное должно уберечь вас от тупиков.

;with cte as
(
  select top 1 *
  from T with (rowlock, readpast)
  where Status = 'Pending'
  order by ID
)
update cte
set Status = 'InProcess'
output inserted.ID, inserted.Status
4 голосов
/ 20 апреля 2011

Это должно сработать

UPDATE [table]
SET Status = 'InProcess'
WHERE Status = 'Pending'

SQL 2008 должен позаботиться о любой блокировке для вас.

0 голосов
/ 16 апреля 2014

Это что-то вроде хака, но у меня он работал для атомарного чтения / обновления:

declare temp1, temp2, ...;
update table
   set temp1=column1,
       temp2=column2, ... 
       column1=expression1,
       column2=expression2, ...
where conditions;
select temp1, temp2, ...;
...