SQL Server 2014: потокобезопасная генерация порядковых номеров - PullRequest
0 голосов
/ 18 марта 2019

Мне нужно сгенерировать прогрессивное число счетов-фактур, избегая пробелов в последовательности:
Вначале я думал, что это довольно просто, как

    SELECT MAX(Docnumber)+1 as NewDocNumber
    from InvoicesHeader

, но, поскольку для созданиязапрос «вставить в InvoiceHeader» и другой запрос может поступить, назначив обеим счетам один и тот же NewDocNumber

. Теперь я думаю не создавать DocNumber в расширенном запросе и изменить его на:

INSERT INTO InvoicesHeader  (InvoiceID,..., DocNumber,...) 
SELECT @InvoiceID,..., MAX(Docnumber)+1,... FROM InvoicesHeader

но хотя (и должно) решить некоторые проблемы, он все еще небезопасен для потока и не подходит для условий гонки:

с добавлением TABLOCK или UPDLOCK, таким образом:

BEGIN TRANSACTION  TR1
    INSERT INTO InvoicesHeader WITH (TABLOCK)  
        (InvoiceID,..., DocNumber,...) 
    SELECT @InvoiceID,..., MAX(Docnumber)+1,... FROM InvoicesHeader
COMMIT TRANSACTION  TR1

Решит вопрос?

Или лучше использовать ISOLATION LEVEL, NEXT VALUE FOR или другое решение?

1 Ответ

0 голосов
/ 18 марта 2019

У вас уже есть поточно-ориентированная генерация последовательности в SQL Server. Читайте о Создать последовательность . Он доступен начиная с SQL Server 2012. Его лучше использовать, поскольку последовательность генерируется вне области транзакции.

Порядковые номера генерируются вне области действия текущего сделка. Они потребляются ли транзакция с использованием порядковый номер зафиксирован или отменен.

Вы можете получить следующее значение из последовательности. Мы использовали последовательности для генерации номеров заказов, и мы не нашли проблем, когда несколько порядковых номеров генерируются параллельно.

SELECT NEXT VALUE FOR DocumentSequenceNumber; 

Обновлено, основываясь на комментариях , если у вас есть четыре разных типа документа, я бы предложил вам сначала сгенерировать последовательность, а затем объединить с определенным типом документа. Вам будет легче понять. В конце года вы можете перезапустить последовательность, используя ALTER SEQUENCE

RESTART [WITH] Следующее значение, которое будет возвращено объект последовательности. Если указано, значение RESTART WITH должно быть целое число, которое меньше или равно максимуму и больше или равно минимальному значению объекта последовательности. Если значение WITH отсутствует, порядковая нумерация перезапускается на основе оригинала Варианты CREATE SEQUENCE.

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