Auto numerar campo na DBF
Moderador: Moderadores
-
Spitzer
- Usuário Nível 2

- Mensagens: 60
- Registrado em: 15 Ago 2003 04:56
- Localização: Nova Fátima - PR
Olá!
Tô contigo, Maligno!
Às vezes passo horas lendo tópicos de perguntas alheias e todas as respostas.
Já aprendi muito com isto. Sempre achamos que temos uma boa solução (quando temos...), mas quando vemos algumas respostas, esta solução sempre pode ser melhorada.
E sobre o ditado, prefiro este: "O que abunda não falta!". hehehehe
Tô contigo, Maligno!
Às vezes passo horas lendo tópicos de perguntas alheias e todas as respostas.
Já aprendi muito com isto. Sempre achamos que temos uma boa solução (quando temos...), mas quando vemos algumas respostas, esta solução sempre pode ser melhorada.
E sobre o ditado, prefiro este: "O que abunda não falta!". hehehehe
Abraços,
Ademir Spitzer
Ademir Spitzer
- Antonio
- Usuário Nível 3

- Mensagens: 347
- Registrado em: 14 Ago 2003 17:33
- Localização: Sao Paulo - SP
- Contato:
Maligno escreveu:Uma vez que uma receita a mais vem a somar no leque de opções, passo a minha também.
Já usei o velho esquema de incrementar o valor do campo X do último registro. Não dá muito certo, já que há o problema de rede. Coincidências acontecem, principalmente quando há mais usuários fazendo a mesma coisa. Descartei.
Já usei também o esquema de gravar um contador específico para cada empresa (multi-empresa) em arquivo à parte. Até dá certo. Funciona bem, mas achei um esquema muito mais prático e simples.
Eu uso agora, plenamente satisfeito, simples números aleatórios. O campo do código, ao ser preenchido, recebe um número gerado ao acaso (Random()). Isso por si só já dá muita tranqüilidade, pois é realmente difícil que dois números se repitam. E nenhum arquivo extra precisa ser manipulado. Portanto, é mais rápido. E também mais fácil - usa menos código. Só que a Lei de Murphy nunca descansa. Então, por precaução, após obter esse número, pesquiso no arquivo e me certifico de que ele realmente não existe. Se existir (raríssimo - nos meus testes nunca peguei um único caso), é só gerar outro número e pesquisá-lo novamente.
Evidentemente, a unicidade do número também depende de sua largura. Se for um número pequeno é óbvio que as chances de repetição são maiores. Uso um número largo o suficiente. Mas aí entra outro problema: não gosto de gastar muito espaço em registro. Assim, inventei um esquema bem simples: números alfadecimais. Parecidos com os hexadecimais, essa base nova usa todas as letras do alfabeto (maiúsculas/minúsculas). Um exemplo: o decimal 56.800.235.583 equivale ao número alfadecimal "zzzzzz". Assim, ao invés de usar 11 caracteres para armazenar um código decimal, uso apenas 6 para essa nova base.
[]'s
Maligno
http://www.buzinello.com/prg
Boa Noite a todos!
Prezado Maligno,
Desculpe se eu estiver sendo um tanto ignorante, mas na pratica não entendi muito bem esse esquema do (Randon()). Veja: estou cadastrando itens..... esses itens são numerados.... 000001, 000002...... 00000n.
Como utilizar (Randon()) da forma sugerida?
Antonio Carlos
Harbour 3.2 (20180213)
Hwgui 2.20 3b | PostGresql 9.5 | ADO/ODBC
Harbour 3.2 (20180213)
Hwgui 2.20 3b | PostGresql 9.5 | ADO/ODBC
- rochinha
- Administrador

- Mensagens: 4664
- Registrado em: 18 Ago 2003 20:43
- Localização: São Paulo - Brasil
- Contato:
Amiguinhos
Sou da mesma opnião do Maligno,
E por mais que eu já tenha andado, apanhado e descoberto tantas coisas, sempre existe algum detalhe que passou despercebido e/ou por falta de necessidade não foi explorado.
O mundo é como um DO..While, giramos, mas passamos sempre pelo mesmo lugar.
@braços :?)
Sou da mesma opnião do Maligno,
E por mais que eu já tenha andado, apanhado e descoberto tantas coisas, sempre existe algum detalhe que passou despercebido e/ou por falta de necessidade não foi explorado.
O mundo é como um DO..While, giramos, mas passamos sempre pelo mesmo lugar.
@braços :?)
Não se desculpe. A ignorância é parte importante do aprendizado. Até porquê se eu próprio fosse pedir desculpas pela minha ignorância em diversos assuntos, viveria me desculpando.Antonio escreveu:Desculpe se eu estiver sendo um tanto ignorante, mas na pratica não entendi muito bem esse esquema do (Randon()). Veja: estou cadastrando itens..... esses itens são numerados.... 000001, 000002...... 00000n.
Antes da explicação, quero primeiro criar um pressuposto. Explico: esses números de controle, para mim, servem única e exclusivamente para dar suporte à criação de vínculos referenciais. São os números que ligam, por exemplo, duplicatas aos clientes que deverão pagá-las. Eu não permito que o usuário use este número para selecionar um cliente, fornecedor, etc. Para isso eu disponho de métodos que acho mais eficientes. Prefiro realmente manter meus usuários afastados desse tipo de código.
Talvez sua filosofia de trabalho seja diferente. Mas vou partir do pressuposto que você pensa como eu e prefere manter seus usuários longe desses números.
Eu estou dizendo isso tudo apenas porquê números seqüenciais são mais "amigáveis" que números aleatórios na forma como eu os represento em arquivo, conforme a explicação a seguir.
Quando precisamos implementar uma solução para criar códigos numéricos de controle, é natural que pensemos no velho esquema do último + 1. Uma seqüência crescente, sem o reaproveitamento de códigos de registros apagados. Esse é o pensamento natural.
Mas, como esse número não estará acessível ao usuário, ele não precisa necessariamente ser um número rigorosamente seqüencial. Pode ser um número qualquer, pego ao acaso, através de algum gerador de números aleatórios, do tipo que se obtém com a função Random() da CATools, que é a função que eu uso para este fim. Uma grande vantagem a destacar: como é um número aleatório, precisamos apenas de uma pequena porção do tempo da CPU para obtê-lo. Por outro lado, um número seqüencial requer uma ida ao fim do arquivo de dados. Isso requer muito mais processamento. Pior ainda no caso dos contadores sendo armazenados em arquivos à parte, como eu próprio fazia no passado. Muito mais tempo de CPU será necessário, já que isso implica numa prévia abertura deste arquivo e a busca por uma chave de identificação do contador. Assim, gerar um número aleatório é muito mais rápido. Só há um porém: um número, sendo aleatório, pode já existir no arquivo de dados, em algum registro. É muito difícil disso acontecer. Principalmente se for um número razoavelmente largo, com uns 9 dígitos ou mais, digamos assim. Mas eu sou por natureza muito desconfiado. Por isso, para não ser pego com as calças na mão, após gerar o número, me certifico de que ele é realmente único, pesquisando-o no arquivo. Como esse código sempre faz parte de uma chave de índice, essa pesquisa é extremamente rápida.
Assim foi a primeira parte da explicação: porquê e como gerar o número aleatório e garantir sua unicidade.
A segunda parte diz respeito à forma de armazenar esse número. Isso é uma característica à parte. Nem é tão essencial ao processo em si. você poderá armazenar esse código do jeito que melhor lhe aprouver. Mas eu tenho a mania de sempre querer economizar algum espaço nos registros. Para isso eu utilizo uma nova base numérica, chamada de alfadecimal, que é semelhante à base hexadecimal, mas que utiliza todas as letras do alfabeto (ou mais). Não sei se você tem interesse nisso. Mas a título de curiosidade, observe a tabela abaixo. Há três tipos de bases: alfadecimal simples (apenas letras maiúsculas), extendida (inclui também as minúsculas) e super-extendida (inclui também alguns caracteres gráficos - mas imprimíveis). Note bem o ganho de espaço na conversão. No melhor caso, uso apenas 9 dígitos do alfadecimal super-extendido para representar um número decimal de 18 dígitos.
Uma curiosidade: dada a natureza dos dados com os quais trabalho, meus códigos de identificação tem apenas 6 dígitos e eu uso a base alfadecimal simples, com letras maísculas apenas. Para o meu caso é suficiente.
Código: Selecionar todos
Dígitos Alfadedimal Decimal Dígitos
------- ----------- ----------------------- -------
1 Z = 35 2
2 ZZ = 1.295 4
3 ZZZ = 46.655 5
4 ZZZZ = 1.679.615 7
5 ZZZZZ = 60.466.175 8
6 ZZZZZZ = 2.176.782.335 10
7 ZZZZZZZ = 78.364.164.095 11
8 ZZZZZZZZ = 2.821.109.907.455 13
9 ZZZZZZZZZ = 101.559.956.668.415 15
Alfadecimal
Dígitos Extendido Decimal Dígitos
------- ----------- ----------------------- -------
1 z = 61 2
2 zz = 3.843 4
3 zzz = 238.327 6
4 zzzz = 14.776.335 8
5 zzzzz = 916.132.831 9
6 zzzzzz = 56.800.235.583 11
7 zzzzzzz = 3.521.614.606.207 13
8 zzzzzzzz = 218.340.105.584.895 15
9 zzzzzzzzz = 13.537.086.546.263.550 17
Alfadecimal
Super
Dígitos Extendido Decimal Dígitos
------- ----------- ----------------------- -------
1 ~ = 93 2
2 ~~ = 8.835 4
3 ~~~ = 830.583 6
4 ~~~~ = 78.074.895 8
5 ~~~~~ = 7.339.040.223 10
6 ~~~~~~ = 689.869.781.055 12
7 ~~~~~~~ = 64.847.759.419.263 14
8 ~~~~~~~~ = 6.095.689.385.410.815 16
9 ~~~~~~~~~ = 572.994.802.228.616.700 18[]'s
Maligno
http://www.buzinello.com/prg
PS: Na verdade eu utilizo uma combinação das funções Rand() e Random().
- Antonio
- Usuário Nível 3

- Mensagens: 347
- Registrado em: 14 Ago 2003 17:33
- Localização: Sao Paulo - SP
- Contato:
Bom dia Maligno!
Bem... ficou claro sim, abrigado pela atenção e pelos esclarecimentos.
Quanto a numerar sequencialmente, o que me foi mais conveniente até o momento é exatamente a forma de utilização de um contador num DBF a parte. Veja:
No inicio abro todos os DBFs "base de dados e contadores", no momento do cadastro seleciono o numerador e pego o valor do campo no arquivo, igualo uma variavel a este numero para posteriormente efetivar o cadastro, incremento +1 ao valor do campo numerador e libero o mesmo para os proximos usuarios. Não faço nenhuma pesquisa antes de efetuar o cadastro, pois em tese não haveria como um numero colidir em igualdade, ja que ele é incrementado em 1 e no momento em que pego esse valor, o registro esta bloqueado.... Bem essa é forma que venho utilizando.
[]s
Bem... ficou claro sim, abrigado pela atenção e pelos esclarecimentos.
Quanto a numerar sequencialmente, o que me foi mais conveniente até o momento é exatamente a forma de utilização de um contador num DBF a parte. Veja:
No inicio abro todos os DBFs "base de dados e contadores", no momento do cadastro seleciono o numerador e pego o valor do campo no arquivo, igualo uma variavel a este numero para posteriormente efetivar o cadastro, incremento +1 ao valor do campo numerador e libero o mesmo para os proximos usuarios. Não faço nenhuma pesquisa antes de efetuar o cadastro, pois em tese não haveria como um numero colidir em igualdade, ja que ele é incrementado em 1 e no momento em que pego esse valor, o registro esta bloqueado.... Bem essa é forma que venho utilizando.
[]s
Antonio Carlos
Harbour 3.2 (20180213)
Hwgui 2.20 3b | PostGresql 9.5 | ADO/ODBC
Harbour 3.2 (20180213)
Hwgui 2.20 3b | PostGresql 9.5 | ADO/ODBC
- Antonio
- Usuário Nível 3

- Mensagens: 347
- Registrado em: 14 Ago 2003 17:33
- Localização: Sao Paulo - SP
- Contato:
Ola Janio!janio escreveu:Olá Antonio,
Entendi perfeitamente seu ponto de vista. O que não foi claro foi na hipótese de o usuário, no meio de um cadastro, desistir de continuar o cadastro. E aí, esse número, no caso, ficou "perdido"?
Janio
Hipotéticamente sim..... mas não é o fim....
No meu caso uso numeros "caracteres" sequenciais entre 00000 e 99999. Serão cerca de 100.000 itens, por esse motivo não levo em conta a razão entre o cadastro efetivo e o não concluido, contudo pode-se isolar essa situação de inicio de cadastro e desistencia sem a efetiva gravação, no meu caso não implementei ainda, mas poderei faze-lo futuramente....
Ficou claro?
Antonio Carlos
Harbour 3.2 (20180213)
Hwgui 2.20 3b | PostGresql 9.5 | ADO/ODBC
Harbour 3.2 (20180213)
Hwgui 2.20 3b | PostGresql 9.5 | ADO/ODBC
- Augusto
- Usuário Nível 3

- Mensagens: 473
- Registrado em: 26 Ago 2003 17:50
- Localização: Maricá/RJ
- Contato:
Re: Numerar Campo em uma DBF
Está tudo muito bem.... Diante de tantas opções, muitas das quais eu concordo plenamente, outras em parte e poucas eu descorde e, com o problema do nosso colega efetivamente resolvido, só me resta fazer uma pergunta...kristo escreveu:Eu poderia auto numerar no access, mais infelizmente ele não comporta abrir tantos nomes
Seria eu "sortudo" de ter uma tabela ACCESS em um MDB de meus clientes com 11.753.123 registros ?? e diga-se de passagem com muito mais campos do que o DBF do colega... Não causa estranhesa que um DBF comporte 8.000.000 de regs, segundo o colega e uma tabela ACCESS não ??
Alguém poderia me esclarecer ??
:xau Fui...
goulart@provsul.com.br
Faça da PROVSUL o seu Provedor de Serviços WEB
Visite: www.PROVSUL.com.br
goulart@provsul.com.br
Faça da PROVSUL o seu Provedor de Serviços WEB
Visite: www.PROVSUL.com.br
Amigo, sobre o "número perdido" eu tinha esse problema, teve um cliente que vivia reclamando que havia "lacunas" nos números dos orçamentos que se não existissem tornaria o controle mais fácil e confiável.janio escreveu:Olá Antonio,
Entendi perfeitamente seu ponto de vista. O que não foi claro foi na hipótese de o usuário, no meio de um cadastro, desistir de continuar o cadastro. E aí, esse número, no caso, ficou "perdido"?
Janio
Pois bem, hoje em todos os meus sistemas só atribuo o número sequencial no momento que o usuário der entrada no último campo, então se ele começar uma inclusão digitar alguns dados e em seguida desistir teclando ESC, nenhum número será perdido.
Sucesso a todos.
-
spereira
- Usuário Nível 2

- Mensagens: 85
- Registrado em: 19 Jul 2004 11:42
- Localização: Porto - Portugal
Olá Maligno,
Gostaria de testar esta função random() da CATools.
Onde posso conseguir esta biblioteca?
Hoje utilizo uma função própria que gera números aleatórios de acordo com o limite que eu informar, mas acontece de repetir muito os números e, com isto, atraza o processo pois tenho que verificar se o número já não foi gerado e voltar a gerar outro número.
Como você disse que é raro de haver números repetidos gerados por esta função random(), então para mim seria excelente.
Gostaria de testar esta função random() da CATools.
Onde posso conseguir esta biblioteca?
Hoje utilizo uma função própria que gera números aleatórios de acordo com o limite que eu informar, mas acontece de repetir muito os números e, com isto, atraza o processo pois tenho que verificar se o número já não foi gerado e voltar a gerar outro número.
Como você disse que é raro de haver números repetidos gerados por esta função random(), então para mim seria excelente.
Pro Janio e Antonio
O caso que o antonio citou é mais interessante,
pois os números serão sequenciais, facilitando
ordenações entre outras pesquisas.
No caso, para evitar as lacunas, caso o usuário
desista, basta deixar para pegar o COD apenas
no momento exato de inserir o novo Registro.
Assim, no momento do cadastro, o usuário não
teria conhecimento do código. Apenas após
confirmar a adição do novo registro, é que o
sistema iria na tabela, bloquearia os codigos,
pegava o ultimo código, incrementaria-o,
desbloqueava, e adicionava o registro do usuário.
E no fim, exibiria para o usuário o CÓDIGO do
novo Registro adicionado.
pois os números serão sequenciais, facilitando
ordenações entre outras pesquisas.
No caso, para evitar as lacunas, caso o usuário
desista, basta deixar para pegar o COD apenas
no momento exato de inserir o novo Registro.
Assim, no momento do cadastro, o usuário não
teria conhecimento do código. Apenas após
confirmar a adição do novo registro, é que o
sistema iria na tabela, bloquearia os codigos,
pegava o ultimo código, incrementaria-o,
desbloqueava, e adicionava o registro do usuário.
E no fim, exibiria para o usuário o CÓDIGO do
novo Registro adicionado.


