Página 1 de 1

Verificando se valor já existe no banco

Enviado: 21 Fev 2017 18:11
por ClickOk
Olá amigos

Tenho um requerimento de um cliente, que é assim: Tem um certo campo "CODIGO", onde ele quer que o usuário não possa adicionar um código repetido, isto é, que já exista no banco de dados. A linha é assim:

Código: Selecionar todos

 @  10, 10 GGET cCODIGO PICTURE "@!" VALID ! Empty(cCODIGO) MESSAGE "Informe o codigo (obrigatório)"
então, o que eu fiz: criei uma função

Código: Selecionar todos

FUNCTION CodigoExiste(codigo)
  nAreaAntiga := Select()
  DbSelectArea("Produtos")
  dbseek(codigo)
  achou := found()
  Select(nAreaAntiga )
return achou
e coloquei no VALID:

Código: Selecionar todos

 @  10, 10 GGET cCODIGO PICTURE "@!" VALID ! Empty(cCODIGO)  .and. !CodigoExiste(cCODIGO);
MESSAGE "Informe o codigo (obrigatório)"
A função está sendo chamada direitinho, mas deu um problema de indices. Daí descobri que o programador anterior não criou índices para o campo CODIGO (criou para outros campos), por isso provavelmente o dbseek nem funciona nesse caso.

Como é uma tabela grande, e locate é inviável, preciso criar um indice para usar apenas nesse trecho de código. E tem que ser de um jeito mais ou menos assim:
1) Guardar indice atual
2) Usar novo indice
3) restaurar indice antigo quando acabar de usar

Isso porque é um sistema existente e complexo, então não posso correr o risco de não de colocar de volta o indice anterior. Viram como salvei a area antiga e depois restaurei? parecido...

Agradeço antecipadamente!

Verificando se valor já existe no banco

Enviado: 21 Fev 2017 18:36
por alxsts
Olá!

Se é uma tabela grande, não é recomendável criar índice a cada execução. Crie um índice permanente e use sempre que precisar. Nem precisa de função no VALID. Veja:

Código: Selecionar todos

   10, 10 GET cCODIGO ;
      PICTURE "@!" ;
        VALID (! Empty(cCODIGO) .AND. If( Produtos->( DbSeek( cCODIGO ) ), Alert( "Código já cadastrado" ) == -1, .T. ) ) ;
      MESSAGE "Informe o codigo (obrigatório)"
Quando se usa o operador ALIAS ( -> ) o próprio Clipper controla a alteração e restauração da área corrente.

O único cuidado que você precisará tomar será verificar todos os programas que incluam, excluam ou alteram registros nesta tabela e abrir em cada um deles o novo índice que irá criar. Caso contrário, os índices não serão atualizados.

Verificando se valor já existe no banco

Enviado: 21 Fev 2017 18:47
por ClickOk
Obrigado, alexandre. Sua reposta ajudou muito!

Só mais uma dúvida. Você disse "Crie um índice permanente e use sempre que precisar.". Mas não vejo o código de criação dos indices no código do antigo programador... e quando ele vai usar o índice, ele usa "dbsetindex()" (e pelo que vi na documentação do clipper, já está ultrapassado).

Que eu me lembre, para criar e usar índices, eu usava "INDEX ON .. TO" e "SET INDEX TO"... Então, estou meio confuso... Pode, por favor, dar um exemplo simples de como que faço para criar e usar um índice?

Verificando se valor já existe no banco

Enviado: 21 Fev 2017 19:15
por alxsts
Olá!
ClickOk escreveu:Mas não vejo o código de criação dos indices no código do antigo programador...
Este sistema onde você está fazendo alterações deve ter uma rotina de criação e recriação de índices. Isto é comum em sistemas escritos em Clipper. Procure.

Nesta rotina, já deve ter a criação dos índices da tabela em questão (Produtos, pelo que deduzi do código postado). Acrescente então o código para criar mais um índice. Algo assim se estiver usando o driver DBFNTX:

Código: Selecionar todos

USE Produtos EXCLUSIVE NEW
INDEX ON codigo TO prodCod
USE
Verificar todos os programas que utilizam esta tabela e acrescentar a abertura de mais um índice. Isto fica fácil com um editor de texto que tenha "Find in Files". Algo assim:

Código: Selecionar todos

USE Produtos SHARED NEW
SET INDEX TO ind1, ind2, ind3....., prodCod
Quanto ao SET INDEX versus DbSetIndex(), é uma questão de escolha. Não sei qual documentação você leu mas não há nada de ultrapassado com elas. SET INDEX é um comando que, durante a compilação, é substituído pela função DdSetIndex(). Muitas funcionalidades do Clipper estão disponíveis na forma de comando ou função.

Verificando se valor já existe no banco

Enviado: 21 Fev 2017 19:29
por ClickOk
Obrigado, ajudou bastante!

Quanto a estar ultrapassado, li nesses docs:
https://harbour.github.io/ng/c53g01c/ng3228f.html
DBSETINDEX() is a compatibility command and therefore is not
recommended. It is superseded by the ORDLISTADD() function.

Verificando se valor já existe no banco

Enviado: 22 Fev 2017 10:47
por alxsts
Olá!

Isto é verdade a partir do Clipper 5.3 e Harbour ou xHarbour. Se você usa Clipper 5.2 ainda são atuais.

Verificando se valor já existe no banco

Enviado: 27 Fev 2017 12:29
por rochinha
Amiguinhos,

As diferenças entre o dbSetIndex() e o OrdListAdd() é que dbSetIndex() seria uma função definitiva enquanto o OrdListAdd() é uma função on-the-fly.

Explicando melhor cada chamada dbSetIndex() refaz a mesma enquanto OrdListAdd() permite adicionar ordens a lista existente. Como quando se adiciona valores a um vetor. Mutio melhor que dbSetIndex().