Это простое решение. Состояние гонки. Отсутствие блокировки от уровня изоляции ограничительных транзакций. Вероятно, не будет работать в SQL-диалектах, отличных от T-SQL.
Я предполагаю, что это некоторая внешняя сила на работе, чтобы сохранить таблицу каталогов, заполненную неназначенными номерами каталогов.
Этот метод должен работать для вас: просто сделать такое же «заблокированное обновление», который извлекает значение, что-то вроде:
update top 1 CatalogNumber
set in_use = 1 ,
@newCatalogNumber = catalog_number
from CatalogNumber
where in_use = 0
Во всяком случае, следующая хранимая процедура просто просто клещи до номера на каждом выполнение и отмена предыдущей. Если вы хотите значение fancier, добавьте вычисленный столбец, который применяет преобразование выбора к инкрементному значению для получения желаемого значения.
drop table dbo.PrimaryKeyGenerator
go
create table dbo.PrimaryKeyGenerator
(
id varchar(100) not null ,
current_value int not null default(1) ,
constraint PrimaryKeyGenerator_PK primary key clustered (id) ,
)
go
drop procedure dbo.GetNewPrimaryKey
go
create procedure dbo.GetNewPrimaryKey
@name varchar(100)
as
set nocount on
set ansi_nulls on
set concat_null_yields_null on
set xact_abort on
declare
@uniqueValue int
--
-- put the supplied key in canonical form
--
set @name = ltrim(rtrim(lower(@name)))
--
-- if the name isn't already defined in the table, define it.
--
insert dbo.PrimaryKeyGenerator (id)
select id = @name
where not exists (select *
from dbo.PrimaryKeyGenerator pkg
where pkg.id = @name
)
--
-- now, an interlocked update to get the current value and increment the table
--
update PrimaryKeyGenerator
set @uniqueValue = current_value ,
current_value = current_value + 1
where id = @name
--
-- return the new unique value to the caller
--
return @uniqueValue
go
Чтобы использовать его:
объявить @pk Int Exec @pk = dbo.GetNewPrimaryKey 'Foobar' выберите @pk
Trivial моднику его возвращать результирующий набор или вернуть значение через параметр OUTPUT.
Все три этапа хранимой процедуры заключены в транзакцию? Каков уровень изоляции, установленный для транзакции? – Thomas
Это также апокалипсис, если у вас есть пробелы в присвоенных номерах каталогов? т. е. если T1 присваивается номер каталога, а затем удаляет ошибку, тогда откатывается, это проблема, если этот номер каталога просто пропущен? –
Извините, позвонили и не смогли контролировать мой собственный вопрос. Итак, 1) нет, они сейчас не находятся в транзакции, просто выполняются один за другим в одном и том же sproc. и 2) идеальные арки, но они далеки от апокалиптического –