В транзакции всегда выполняется одно UPDATE, поэтому два сеанса, пытающихся выполнить одно и то же обновление, будут сериализованы (один произойдет раньше другого). Так что вам просто нужно определить, было ли уже обновлено бронирование, когда вы его обновляете.
Один простой способ сделать это - отфильтровать обновление по vacant = 1
, а затем проверить @@rowcount
после обновления, чтобы увидеть, не повлияло ли оно на какие-либо строки. Например:
update Booking set vacant = 0
where house_id = @house_id
and week_no = @weekno
and vacant = 1
if @@rowcount = 0
begin
throw 50001, 'House not vacant for that week', 1;
end
Если вы отметите vacant
в отдельном запросе, вам понадобится явная транзакция и подсказка updlock
, чтобы при проверке состояния сеанса получалась и сохранялась блокировка, которая помешала бы другому сеансуизменение статуса, например:
begin transaction
declare @vacant bit =
(
select vacant
from Booking with (updlock)
where house_id = @house_id
and week_no = @weekno
)
if @vacant = 1
begin
update Booking set vacant = 0
where house_id = @house_id
and week_no = @weekno
commit transaction
end
else
begin
rollback
throw 50001, 'House not vacant for that week', 1;
end