Я обычно использую что-то вроде этого:
update OrderNumberInfo with (rowlock)
set @OrderNumber = OrderNumber, OrderNumber = OrderNumber + 1
where VendorID = @VendorID
Не нужно заключать в транзакцию. Фактически, если вы включите его в транзакцию, SQL Server начнет удерживать блокировки таблицы и замедлит все. Когда мне нужно сделать что-то подобное в веб-сервисе, я всегда выполняю его на отдельном соединении с базой данных вне любой транзакции, которая может быть открыта в данный момент, просто чтобы убедиться.
Я считаю (но не доказал), что SQL Server использует защелку, а не транзакцию, чтобы сделать ее атомарной, что должно быть более эффективным.
Если ваш дизайн таблицы таков, что строка поставщика должна быть создана по требованию, если она не существует, используйте вместо этого следующую логику:
declare @error int, @rowcount int
-- Attempt to read and update the number.
update OrderNumberInfo with (rowlock)
set @OrderNumber = OrderNumber, OrderNumber = OrderNumber + 1
where VendorID = @VendorID
select @error = @@error, @rowcount = @@rowcount
if @error <> 0 begin
return @error
end
-- If the update succeeded then exit now.
if @rowcount > 0 begin
return 0
end
-- Insert the row if it doesn't exist yet.
insert into OrderNumberInfo (VendorID, OrderNumber)
select VendorID, 1
where not exists (select null from OrderNumberInfo where VendorID = @VendorID)
select @error = @@error
if @error <> 0 begin
return @error
end
-- Attempt to read and update the number.
update OrderNumberInfo with (rowlock)
set @OrderNumber = OrderNumber, OrderNumber = OrderNumber + 1
where VendorID = @VendorID
select @error = @@error
if @error <> 0 begin
return @error
end
Этот код по-прежнему не требует транзакции, потому что каждый атомарный оператор будет успешным независимо от того, сколько других соединений выполняет код одновременно.
Отказ от ответственности: Я использовал это без проблем на SQL Server 7-2005. Я пока не могу комментировать его поведение в 2008 году.