Tenho um requisito comercial de que cada registro na tabela Fatura tenha um ID parecido com YYYYNNNNNN.
A parte NNNNNN precisa ser reiniciada no início de cada ano. Portanto, a primeira linha inserida em 2016 se pareceria com 2016000001 e a segunda como 2016000002 etc. Vamos dizer que o último registro para 2016 foi 2016123456, a próxima linha (de 2017) deve ser 2017000001
Não preciso que esse ID seja a chave primária e também armazeno a data de criação. A ideia é que esse 'ID de exibição' seja único (para que eu possa consultar) e capaz de agrupar pessoas por ano.
É improvável que quaisquer registros sejam excluídos; no entanto, eu estaria inclinado a codificar defensivamente contra algo assim.
Existe alguma maneira de criar esse ID sem precisar consultar o ID máximo este ano toda vez que inserir uma nova linha?
Ideias:
- A
CreateNewInvoiceSP
, que obtém oMAX
valor para esse ano (nojento) - Algum recurso mágico incorporado para fazer exatamente isso (eu posso sonhar direito)
- Ser capaz de especificar alguma UDF ou algo na declaração
IDENTITY
ouDEFAULT
(??) - Uma exibição que usa
PARTITION OVER + ROW()
(excluída seria problemática) - Um gatilho ativado
INSERT
(ainda seria necessário executar umaMAX
consulta :() - Um trabalho anual anterior, atualizava uma tabela com o MAX para cada ano inserido, que eu então ... Algo ?!
Todos os quais são um pouco não ideais. Todas as idéias ou variações são bem-vindas!
fonte
Respostas:
Existem 2 elementos no seu campo
Eles não precisam ser armazenados como um campo
Exemplo:
YEAR(GETDATE())
Em seguida, crie uma coluna computada concatenando-os (com formatação apropriada). A sequência pode ser redefinida na mudança de ano.
Código de exemplo no SQLfiddle : * (o SQLfiddle nem sempre funciona)
fonte
SEQUENCE
no início de cada ano?NEXT VALUE FOR
em umaCASE
declaração (eu tentei)Você considerou criar um campo de identidade com seed = 2016000000?
Essa semente deve ser incrementada automaticamente a cada ano. Por exemplo, na noite de 2017/1/1, você precisa agendar
Mas já vejo problemas com o design, por exemplo: e se você tiver milhões de registros?
fonte
O que eu fiz nesse cenário foi multiplicar o ano por 10 ^ 6 e adicionar o valor da sequência a isso. Isso tem a vantagem de não exigir um campo computado com sua sobrecarga contínua (pequena) e o campo pode ser usado como um
PRIMARY KEY
.Existem duas dicas possíveis:
verifique se o seu multiplicador é suficientemente grande para nunca se esgotar e
você não tem uma sequência garantida sem lacunas devido ao armazenamento em cache da sequência.
Eu não sou especialista em SQL Server, mas você provavelmente pode definir um evento para disparar em 201x 00:00:00 para redefinir sua sequência para zero. Também foi o que fiz no Firebird (ou foi o Interbase?).
fonte
Edit: Esta solução não funciona sob carga
Eu não sou fã de gatilhos, mas parece melhor que eu poderia malhar.
Prós:
Editar: Contras:
(Crédito para @gbn quando me inspirei na resposta deles) (Qualquer feedback e apontando os erros óbvios são bem-vindos :)
Adicionar alguns novos
COLUMN
s e umINDEX
Adicione o novo
TRIGGER
fonte
NULL
valores. Voltar à prancheta de desenho ...ON Previous.Id = (I.Id -1)
deve apenas procurar), mas sim ainda não funciona. Se eu pudesse bloquear a tabela (?) Durante a inserção e o gatilho, acho que funcionaria. Mas isso também parece um cheiro de código.