SEQUENCE POR EMPRESA
PostGreSQL 9.3
Uso a criação de Sequences com bastante facilidade, até porque não há dificuldade no uso dos mesmos. é algo bem simples.
Até o momento tenho uma Sequence chamada ProximoCodCli que me fornece o próximo código para o cliente. E tudo funciona muito bem até que....
Mudando o sistema para Web (estou na fase de MER ainda) me chamou atenção para algo na frente. A tabela de clientes conterá CodigoDaEmpresa, CodigoDoCliente, Nome, CNPJCPF, etc...
Para a empresa de código 1 posso ter os clientes de de código 1 à n Mas se eu crio dois cliente na empresa 1 com códigos de cliente 1 e 2 (sequence), quando eu cadastrar um cliente na empresa 5 o código do cliente será 3 (sequence). Eu desejo deixar uma sequence para cada empresa, assim empresa 1 terá clientes e códigos de 1 a n e empresa 5 também com reinicio de sequence (código de 1 a n) e não pegando o último código utilizado na empresa 1.
Imaginei duas soluções:
Cada empresa teria seu banco de dados. Descartei porque a manutenção teria que ocorrer em cada banco de dados (quando houvesse manutenção). é menos trabalhoso e menos sujeito a erros fazer manutenção em um único banco de dados.
Para cada empresa teria uma sequence. Empresa 1 teria a sequence ProximoCodCli_1 e empresa 5 teria a sequence ProximoCodCli_5. Resolve, mas é bem uma solução intrÃnseca do PostGreSQL e sim uma solução baseada em código do sistema (que eu queria evitar, deixando o máximo possÃvel de controle dentro do PostGreSQL e o sistema ser mais voltado para o front-end).
Algum dos colegas tem alguma idéia de como poderia ser contornado o problema sem usar as duas soluções que imaginei?
Tudo de bom.
Eu faria uma tabela de Clientes com a chave composta. Uma parte da chave seria o código da Empresa como chave estrangeira (FK - Foreign Key) e a segunda parte é a própria chave primária (PK - Primary Key).
Por exemplo:
Empresa
CodEmpresa (PK)
Nome
Cliente
CodEmpresa (FK)
CodCliente (PK)
[][ô]s,
Tunusat.
Exemplo:
Empresa 1
Cliente 1
imaginando que a chave de acesso seja numérica:
ChaveAcesso = (Empresa * 100000) + Cliente = 100001
Para não ter que digitar este código enorme na digitação pega Empresa e Cliente em Campos Separados.
Saudações
A sugestão do colega Tunusat eu já utilizo, faz validação mas não impede de ficarem pulos na sequence, como narrei na abertura do post.
O colega NetMania sugere uma sequence para cada empresa, o que também na abertura do post eu havia dito ser uma das opções, mas que não deseja utilizar para que tudo fosse criado/mantido pelo próprio postgres e o sistema ficasse com sua finalidade inicial de ser o front-end apenas.
Acredito que a solução será uma mistura das opções: criar uma função que recebe o código da empresa e caso já exista sequence para a mesma, apenas retornará o próximo código na sequence. Caso não exista sequence para a empresa, criará a mesma e então retornará o código de cliente através da própria. Precisará ter padrão de nome da sequence, que imagino ser [Ô]seq_[Ô] seguido do código da empresa, seguido por [Ô]_codcli[Ô] (exemplo: seq_5_codcli para a sequence de clientes da empresa 5). Embora utilizando uma das duas alternativas que coloquei na abertura do post (e que não deseja utilizar), acredito que assim ficaria tudo dentro do postgres e, para chegar-se ao próximo código de cliente seria apenas um select na função passando o código da empresa como parâmetro, algo como Select ProximoCodigoCliente(5) para pegar o próximo código de cliente da empresa 5 (se [Ô]seq_5_codcli[Ô] não existir será criada).
Vou deixar o post ainda aberto por mais 1 dia, para que os colegas que desejarem manifestarem suas idéias e opniões.
Tudo de bom.
Mas ... desculpe ... não entendi ... em que caso ficaria com [Ô]pulos na sequence[Ô]?
Por exemplo se você cadastrar:
1º) Caso:
Empresa - 1
Cliente - 1
2º) Caso:
Empresa - 2
Cliente - 1
São dois registros distintos, certo?
A chave seria composta (em campos separados):
1º) Caso a Chave ficará assim: [Ô]1 e 1[Ô];
1º) Caso a Chave ficará assim: [Ô]2 e 1[Ô];
Só ocorreriam [Ô]pulos[Ô] em caso de desistência de cadastramento. Vamos supor que duas pessoas estão cadastrando clientes para a Empresa [Ô]2[Ô].
Dai pegam duas chaves a saber:
3º) Caso:
Empresa - 2
Cliente - 2
4º) Caso:
Empresa - 2
Cliente - 3
Mas a primeira pessoa simplesmente desiste ou cai a energia e a chave [Ô]2 e 2[Ô] é perdida (caso 3º) ...
... bom ... o próximo número de chave seria [Ô]2 e 4[Ô]. Então a chave [Ô]2 e 2[Ô] ficaria sem uso ... seria este o problema?
*** Outra idéia:
- Criar uma tabela de [Ô]controle[Ô] que teria obrigatoriamente todas as PKs das empresas cadastradas em forma de registros. Uma vez criada a empresa é obrigatório criar um registro para ela nesta tabela. E nesta tabela um dos campos seria um [Ô]sequence[Ô] que armazenaria o último número utilizado pelo cliente. Mas ele só pode ser atualizado quando for confirmado a criação do registro de novo cliente. Isto complicaria a manutenção, porém você pode colocar para cada empresa outros campos de controle personalizando o tratamento de cada empresa. Ficaria assim, por exemplo:
Tabela de controle [Ô]tblControlEmpresa[Ô].
Campos:
- IdEmpresa;
- SequenceCliente;
- OutroControleQualquerParaEstaEmpresa;
[][ô]s,
Tunusat.
Mais uma vez grato pela resposta.
No caso de
Citação:- Criar uma tabela de [Ô]controle[Ô] que teria obrigatoriamente todas as PKs das empresas cadastradas em forma de registros. Uma vez criada a empresa é obrigatório criar um registro para ela nesta tabela. E nesta tabela um dos campos seria um [Ô]sequence[Ô] que armazenaria o último número utilizado pelo cliente. Mas ele só pode ser atualizado quando for confirmado a criação do registro de novo cliente. Isto complicaria a manutenção, porém você pode colocar para cada empresa outros campos de controle personalizando o tratamento de cada empresa. Ficaria assim, por exemplo:
Também foi uma das minhas primeiras tentativas, mas além do controle desta tabela em inserções de dados, considerei que para buscar o código, logo antes do insert dos clientes, bastaria
Select max(codcli) + 1as PrxCodCli from TabClientes Where CodEmp=5
Substutuindo o 5 pelo código da empresa. O código do próximo cliente seria o PrxCodCli da Query anterior. Só não apliquei por seria via código e eu gostaria de deixar tudo dentro do PostGreSQL. Pensei em triggers, functions... mas que ficasse dentro do PostGreSQL.
No outro caso, este que você indicou...
Citação:1º) Caso:
Empresa - 1
Cliente - 1
2º) Caso:
Empresa - 2
Cliente - 1
São dois registros distintos, certo?
A chave seria composta (em campos separados):
1º) Caso a Chave ficará assim: [Ô]1 e 1[Ô];
1º) Caso a Chave ficará assim: [Ô]2 e 1[Ô];
Só ocorreriam [Ô]pulos[Ô] em caso de desistência de cadastramento. Vamos supor que duas pessoas estão cadastrando clientes para a Empresa [Ô]2[Ô].
Dai pegam duas chaves a saber:
3º) Caso:
Empresa - 2
Cliente - 2
4º) Caso:
Empresa - 2
Cliente - 3
Eu já havia tentado. Por algum motivo não funcionou. Empresa 1 ficou com cliente 1. Empresa 1 (novamente) ficou com cliente 2 (até aqui tudo certo)... mas a empresa 2 não ficou com cliente 1 (ficou cliente 3). Olhei e [Ô]re-olhei[Ô] a estrutura do BD e esta certo, tanto a PK quanto FK. Dai resolvi fazer o post. Mas vou tentar novamente, considerando que nas vezes que eu tenha feito eu tenha cometido algum erro básico que não percebi (justamente por ser muito básico pode ser que passe despercebido). Mas vou tentar novamente e posto o resultado.
Grato!
Para não ficar o post aberto, vou encerrá-lo. Acho que a melhor saÃda será mesmo criar uma função que conforme necessário usa ou cria uma sequence para a empresa.
Grato a todos que responderam.
Tudo de bom.