Вы можете по-прежнему получать пробелы, если данные удаляются из таблицы. Но если данные только входят, а не выходят, то при правильном использовании транзакций во внешней таблице последовательности должна быть возможность сделать это хорошо. Не используйте MAX () + 1, поскольку у него могут быть проблемы с синхронизацией, или вам может потребоваться заблокировать больше таблицы (страницы / таблицы), чем требуется.
Иметь последовательную таблицу, в которой есть только одна запись и столбец. Извлекать числа из таблицы атомарно, объединяя поиск и использование в одной транзакции.
begin tran
declare @next int
update seqn_for_invoice set @next=next=next+1
insert invoice (invoicenumber,...) value (@next, ....)
commit
Оператор UPDATE является атомарным и не может быть прерван, а двойное присваивание делает значение @next атомарным. Это эквивалентно использованию предложения OUTPUT в SQL Server 2005+ для возврата обновленного значения. Если вам нужен диапазон чисел за один раз, проще использовать значение PRE-update, а не значение POST-update, т.е.
begin tran
declare @next int
update seqn_for_invoice set @next=next, next=next+3 -- 3 in one go
insert invoice (invoicenumber,...) value (@next, ....)
insert invoice (invoicenumber,...) value (@next+1, ....)
insert invoice (invoicenumber,...) value (@next+2, ....)
commit
Ссылка для Оператор UPDATE SQL Server
SET @variable = column = expression устанавливает для переменной то же значение, что и для столбца. Это отличается от SET @variable = column, column = expression, которое устанавливает переменную в значение перед обновлением столбца.