Eu tenho uma tabela de locais que se parece com isso:
CREATE TABLE Locations (
Id INT NOT NULL AUTO_INCREMENT,
Name VARCHAR(255) NOT NULL,
NextInvoice INT NOT NULL,
PRIMARY KEY (Id)
);
Agora quero criar uma fatura para um local e preciso de um número de fatura.
O número da fatura será igual ao NextInvoice
valor para aquele local. E então devo incrementar esse valor para a próxima fatura.
Lógica muito simples, mas complicada por condições de concorrência e corrida.
Como eu poderia executar essa tarefa de recuperar o próximo número de fatura disponível para um local e, em seguida, incrementar esse valor, e não duplicar ou pular nenhum número quando esse código é chamado mais de uma vez ao mesmo tempo?
Não posso usar um número de incremento automático de restrição exclusiva porque os números podem ser duplicados entre os locais.
Nota: Minhas habilidades principais incluem C# e não necessariamente SQL-Server. Na verdade, estou usando o Entity Framework para isso. Mas não estou acima de escrever um procedimento armazenado, se necessário.
Se a transação que aloca números de faturas for sempre de curta duração e suas necessidades de rendimento forem modestas (alguns 100s de faturas/s), você poderá usar uma tabela de sequência. Não deve ser a tabela "Location" principal, pois as linhas serão bloqueadas com frequência (mas brevemente) exclusivamente. Então
Em seguida, para gerar um novo número de fatura
Se o seu processo de criação de faturas exigir transações de execução mais longa, você poderá pré-gerar quantos InvoiceNumbers precisar e confirmá-los.
E se você precisar gerar muitos novos InvoiceNumbers para um local, poderá adicionar mais de 1 a NextInvoice, por exemplo
set NextInvoice = NextInvoice + @numInvoices
.Se você realmente precisar de alta taxa de transferência, use um único objeto SEQUENCE global ou coluna IDENTITY entre os locais e abandone a ideia de que cada local terá seus próprios números de fatura (mesmo que o modelo de dados permita).