Лучший способ получить полностью последовательные значения int в SQL Server - PullRequest
1 голос
/ 04 апреля 2011

У меня есть бизнес-требование, чтобы поле InvoiceNumber в моей таблице Invoices было полностью последовательным - никаких пробелов, иначе аудиторы могут подумать, что наши бухгалтеры что-то замышляют!

Моя первая мысль былапросто используйте первичный ключ (идентификатор), но если транзакция откатывается, в последовательности появляется пробел.

Поэтому моя вторая мысль - использовать триггер, который в точке вставки ищет самый высокий *Значение 1007 * в таблице добавляет к нему 1 и использует его в качестве InvoiceNumber для новой строки.Простота реализации.

Есть ли потенциальные проблемы с почти одновременными вставками?Например, могут ли две почти одновременные вставки, запускающие триггер одновременно, получить одно и то же «на данный момент самое высокое InvoiceNumber» значение и, следовательно, вставить строки с одинаковым InvoiceNumber?

.отсутствует?Был бы другой подход лучше?

Ответы [ 3 ]

0 голосов
/ 04 апреля 2011
CREATE TABLE dbo.Sequence(
 val int 
 )

Вставить строку с начальным семенем.Затем, чтобы выделить диапазон достаточного размера для вашей вставки (очевидно, вызовите ее в той же транзакции)

CREATE PROC dbo.GetSequence
@val AS int OUTPUT,
@n as int =1
AS
UPDATE dbo.Sequence 
SET @val = val = val + @n;

SET @val = @val - @n + 1; 

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

0 голосов
/ 04 апреля 2011

Вы можете по-прежнему получать пробелы, если данные удаляются из таблицы. Но если данные только входят, а не выходят, то при правильном использовании транзакций во внешней таблице последовательности должна быть возможность сделать это хорошо. Не используйте 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, которое устанавливает переменную в значение перед обновлением столбца.

0 голосов
/ 04 апреля 2011

Создать таблицу, которая отслеживает «счетчики».Для ваших счетов вы можете добавить в эту таблицу некоторую запись, которая отслеживает следующее целое число, которое должно быть использовано.
При создании счета вы должны использовать это значение и увеличить его.При откате транзакции обновление этого счетчика также будет отменено.(Убедитесь, что вы поставили блокировку на эту таблицу, чтобы убедиться, что ни один другой процесс не может использовать такое же значение.)таблица счетов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...