Clipper On Line • Ver Tópico - problema com transferencia de registros dbf

problema com transferencia de registros dbf

Discussão sobre a linguagem CA-Clipper.

Moderador: Moderadores

 

problema com transferencia de registros dbf

Mensagempor Glauco Cruz Costa » 03 Jun 2009 00:14

Estou tentando transferir os registros de 1 DBFs para outro DBFs:
De ARQUI01.DBF para ARQUIV01.DBF

Ambos possuem a mesma estrutura - campos: prontuario, data, cod, local.
O arqui01.DBF está com esses campos todos preenchidos.
O arquiv01.dbf está apenas com o campo prontuario preenchido, mas coincide com os campos PRONTUARIO do arqui01.dbf
A minha idéia foi ir lendo cada arquivo em separado, gravando cada registro em variáveis; depois, fechá-lo e abrir o arquiv01, localizar o registro prontuario correspondente e acrescentar os outros campos.
Mas não está dando certo.
Veja como ficou minha rotina:

USE ARQUI01
GO TOP
PO = RECNO()
CLOSE
DO WHILE PO < 500000
  USE ARQUI01
  GO PO
  PRO = PRONTUARIO
  P = PRONTUARIO
  D = DATA
  C = COD
  L = LOCAL
  SKIP
  IF EOF()
    EXIT
  ENDIF
  PO = RECNO()
  CLOSE
  USE ARQUIV01
  LOCATE FOR PRONTUARIO = P
  REPLACE DATA WITH D
  REPLACE COD WITH C
  REPLACE LOCAL WITH L
  COMMIT
  CLOSE
ENDDO
QUIT


Obrigado, desde já!
Avatar de usuário

Glauco Cruz Costa
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 102
Data de registro: 15 Dez 2005 21:02
Cidade/Estado: Brasília/DF
Curtiu: 0 vez
Mens.Curtidas: 0 vez

Re: problema com transferencia de registros dbf

Mensagempor Eolo » 03 Jun 2009 09:21

Uma sugestão...

use arquiv01.dbf new excl
inde on prontuario to temp
set inde to temp
use arqui01.dbf new excl
go top
do whil !eof()
  sele arquiv01
  seek arqui01->prontuario
  if !found()
     ?"Erro - Prontuário não localizado"
     ?prontuario
  else
    repl data  with arqui01->data
    repl cod   with arqui01->data
    repl local with arqui01->data
  endi
  sele arqui01
  skip
endd
quit
Avatar de usuário

Eolo
Colaborador

Colaborador
 
Mensagens: 1134
Data de registro: 08 Dez 2005 17:24
Cidade/Estado: São Paulo - SP
Curtiu: 0 vez
Mens.Curtidas: 41 vezes

Re: problema com transferencia de registros dbf

Mensagempor Glauco Cruz Costa » 03 Jun 2009 11:54

Valeu!
Deu certo.
Porém, eu também gostaria de saber onde está o erro na minha rotina. Só a título de conhecimento mesmo.
Eu não sou muito bom no uso do SELECT e das setas (->) para se referir aos campos. Por isso apanho muito, e minhas rotinas ficam mais extensas e mais complicadas.
Mas, mesmo assim, gostaria de poder identificar os erros na minha rotina.

Também, gostaria de entender essa rotina.
Se possível, coloque uns // e explicações de cada linha. Principalmente, como foi que o SEEK conseguiu localizar os registros em um dbf e já ter meios de se gravar em outro.
Obrigadão!
Avatar de usuário

Glauco Cruz Costa
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 102
Data de registro: 15 Dez 2005 21:02
Cidade/Estado: Brasília/DF
Curtiu: 0 vez
Mens.Curtidas: 0 vez

Re: problema com transferencia de registros dbf

Mensagempor Eolo » 03 Jun 2009 13:49

Glauco, o assunto - embora simples - é meio extenso pra colocar aqui no forum. Se vc usar o MSN, me adicione (o endereço está no meu perfil e é tanto do MSN quanto de email), aí eu vou lhe passando as respostas.
Avatar de usuário

Eolo
Colaborador

Colaborador
 
Mensagens: 1134
Data de registro: 08 Dez 2005 17:24
Cidade/Estado: São Paulo - SP
Curtiu: 0 vez
Mens.Curtidas: 41 vezes

Re: problema com transferencia de registros dbf

Mensagempor Eolo » 04 Jun 2009 09:31

Glauco, aqui vai uma visão geral de USE, SELECT, ÍNDICES e do operador "->", pra lhe ajudar a entender a função que postei antes.

1. SELECT
Vc pode ter vários DBFs abertos ao mesmo tempo, cada um em uma ÁREA DE TRABALHO distinta, e para mudar o foco de uma para outra área, vc usa o SELECT. Então, vc não precisa abrir e fechar os DBFs como vc fez na sua rotina. Exemplo:

use clientes new // vai ser aberto numa nova (NEW) área disponível
use vendas new // idem
* os dois DBFs estão abertos e disponíveis.
select clientes // vc está na área do arquivo CLIENTES
select vendas // vc está em VENDAS

2. INDICES (LOCATE ou SEEK)
Os registros são gravados (APPENDados) no DBF em ordem sequencial de entrada:
1a. entrada = Eduardo
2a. entrada = Antonio
3a. entrada = Livia

O que o comando LOCATE faz é varrer o arquivo DBF, desde o começo, procurando registro a registro pelo que vc quer. Então, um "LOCATE FOR NOME="XIMENES", num DBF com 1 milhão de registros, vai demorar bastante... Pra evitar isso, use o SEEK. Ele é quase "instantâneo", só que exige um arquivo ÍNDICE (NTX ou CDX ou outros).

O que é o arquivo ÍNDICE? É um arquivo 'paralelo' ao DBF, que guarda, para cada registro, a posição relativa dele na ordem que vc deseja. Pegando o exemplo anterior:

use clientes
index on nome to clientes // cria o arquivo clientes.ntx
set index to clientes // usar o DBF JUNTO com o NTX

Agora, se vc mandar listar o arquivo, vai aparecer o seguinte:
Antonio (registro 2)
Eduardo (registro 1)
Livia (registro 3)
*... em ordem alfabética

3. SELECT e o operador "->"
Aqui vai uma função pra ajudar a entender.

set century on   // seta o ANO com 4 digitos, ex. 2009
set date british // seta a data para ddmmaaaa
use clientes new
index on codigo to clientes
set index to clientes
use vendas new
index on datavenda to vendas
go top
seek ctod("01/06/2006") // procura a primeira venda na data indicada
if found()              // se achou a data...
  do while .t.
    if !datavenda=ctod("01/06/2006")
      exit
    endi
    * mostrar o nome do cliente com base no código que está em VENDAS
    select clientes
    seek vendas->codigo // procura em clientes.dbf o codigo que está no vendas.dbf

    * vc está na área de trabalho CLIENTES mas, com o uso do "->"
    * vc pode se referir a campos de quaisquer outros arquivos abertos:
    ?"Cliente: "+clientes->nome          // pega o campo NOME em CLIENTES
    ?"Venda:   "+vendas->numero          // pega o campo NUMERO em VENDAS
    ?"Data:    "+dtoc(vendas->datavenda) // pega o campo DATAVENDA em VENDAS

    wait "pressione qq tecla"
    sele vendas
    skip
  enddo
else
  ?"Nenhum registro encontrado"
endi
quit
Avatar de usuário

Eolo
Colaborador

Colaborador
 
Mensagens: 1134
Data de registro: 08 Dez 2005 17:24
Cidade/Estado: São Paulo - SP
Curtiu: 0 vez
Mens.Curtidas: 41 vezes

problema com transferencia de registros dbf

Mensagempor Pablo César » 04 Jun 2009 10:56

É isso aí colega Eolo ! É sempre muito bom compartilhar informações aqui no fórum, mesmo que demandem muita atenção e trabalho... tinha ficado muito desapontado quando você pediu para tratar por MSN, mas logo ví que você decidiu contribuir aqui no fórum. Quê bom que você tomou essa decisão ! Valeu !

O exemplo espero que valha para todos nós !
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Avatar de usuário

Pablo César
Usuário Nível 7

Usuário Nível 7
 
Mensagens: 5312
Data de registro: 31 Mai 2006 10:22
Cidade/Estado: Curitiba - Paraná
Curtiu: 142 vezes
Mens.Curtidas: 152 vezes

Re: problema com transferencia de registros dbf

Mensagempor Eolo » 04 Jun 2009 11:17

Sim, mas continua a oferta: se o Glauco precisar e quiser, é só me chamar no MSN.
Avatar de usuário

Eolo
Colaborador

Colaborador
 
Mensagens: 1134
Data de registro: 08 Dez 2005 17:24
Cidade/Estado: São Paulo - SP
Curtiu: 0 vez
Mens.Curtidas: 41 vezes

Re: problema com transferencia de registros dbf

Mensagempor Glauco Cruz Costa » 04 Jun 2009 22:14

Valeu Eolo.

Quanto ao seek, ele pesquisa rápido, mas para gravar num dbf de 1.500.000 registros, por exemplo, após a pesquisa por seek, torna-se rápido também?

Eu queria entender também: se o seek pesquisa no arquivo de índice, como que ao encontrar o registro procurado, já pode dar um REPLACE para alteração ou inclusão no DBF principal?

E, aproveitando, uma outra coisa: como uso o index on em rede?
Se eu fizer assim, dá certo?:

use arquivo shared new

DO WHILE !FLOCK()
@ 24,25 SAY " AGUARDE... "
ENDDO
@ 24,25 SAY " "

index on prontuario to temp
unlock
set index to temp

Dará certo desse jeito para todos os usuários que acessarem o programa?

Obrigado.
Avatar de usuário

Glauco Cruz Costa
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 102
Data de registro: 15 Dez 2005 21:02
Cidade/Estado: Brasília/DF
Curtiu: 0 vez
Mens.Curtidas: 0 vez

Re: problema com transferencia de registros dbf

Mensagempor SandroBelarmino » 05 Jun 2009 11:34

Caro Glauco,
Em relação aos arquivos Indices, o ideal é voce definir quais chaves serão necessárias e já ter esses arquivos criados para poder abrí-los juntamente com o dbf, nesse caso específico que voce citou, o ideal seria voce já ter o arq. indice com a chave prontuario, e já trabalhar o dbf juntamente com esse indice, e criá-lo somente quando necessário, (em alguma rotina de reindexação) e nao sempre que for usar o dbf.
No caso de rede, voce precisa abrir o arquivo dbf em modo exclusivo para criar o arquivo indice, ou seja, ninguem pode estar usando o dbf.
Quanto ao tamanho do dbf (quantidade de registros), eu estou trabalhando com arquivos com mais de 1.000.000 de registros e nao estou tendo problemas, (a não ser quando dá algum pau na rede, o que acontece as vezes em algum cliente) portanto, acho que isso nao será um problema pra voce tambem.

Abraço.
Alessandro R Belarmino
Clipper 5.2e - Blinker 7 - DBFNTX / DBFCDX
"Quem trabalha muito erra muito, quem trabalha pouco erra pouco, quem não trabalha não erra e quem não erra é promovido !!!!"
SandroBelarmino
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 464
Data de registro: 04 Set 2007 16:11
Cidade/Estado: Pedreira-SP
Curtiu: 18 vezes
Mens.Curtidas: 0 vez

Re: problema com transferencia de registros dbf

Mensagempor Eolo » 05 Jun 2009 15:13

Glauco, como parece que vc tá começando, vou fazer um passo-a-passo bem simples, pra vc entender o mecanismo.

POINTER
Existe no Clipper um cara chamado POINTER (ponteiro), que indica em qual registro do DBF você está. Além disso, além dos registros digamos normais, existem no DBF 2 registros "fantasmas": o BOF e o EOF. Pra que? Veja a seguir o funcionamento das funções EOF() e BOF().

1. vc cria um DBF com só um campo NOME e abre ele SEM indice: USE CLIENTES NEW
2. como ele não tem nenhum registro, o POINTER fica no registro BOF = Begin of File = Início de Arquivo
3. se vc fizer GO BOTT (vá pra base), o POINTER vai parar no registro EOF = End of File = Fim de Arquivo

4. APPEND BLANK: o Clipper ADICIONA um registro em branco no arquivo (número 1) e move o POINTER para ele.
5. REPLACE NOME WITH "XIMENES": o registro 1 vai receber esse nome.
6. novo APPEND BLANK: é adicionado o registro número 2 e o POINTER é movido pra ele.
7. REPLACE NOME WITH "ALVARO": o registro 2 vai receber esse nome.
8. novo APPEND BLANK: é adicionado o registro número 3 e o POINTER é movido pra ele.
9. REPLACE NOME WITH "JOSE": o registro 3 vai receber esse nome.
* quer confirmar? faça ?RECNO() -> vai aparecer 3
* RECNO = Record Number = Número do registro

Fica o seguinte:
Reg1 = XIMENES
REg2 = ALVARO
REg3 = JOSE

10. GO TOP (vá pro topo): faz mover POINTER para o topo do arquivo (registro 1 = XIMENES)
11. SKIP (pule): faz o POINTER pular para o próximo registro (2 = ALVARO)
12. SKIP -1 (pule pra trás): faz o POINTER pular para o registro anterior (1 = XIMENES)
13. GO BOTT (vá pra base): faz mover o POINTER para o fim do arquivo (registro 3 = JOSE)
14. LOCATE FOR NOME="ALVARO": procura pelo nome e move o POINTER para o registro 2
15. LOCATE FOR NOME="XPTO": procura e, como não achou, move o POINTER para o EOF

Bem, até aqui foi SEM indice. Então o SKIP e o GO TOP/BOTT fizeram o POINTER ser movido de acordo com a ordem natural dos registros (ordem de entrada). Agora, vamos usar um ÍNDICE:
16. INDEX ON NOME TO CLIENTES
17. Daqui pra frente, não é mais a ordem natural (de gravação), mas a ordem alfabética do campo NOME. O arquivo DBF continua guardando os nomes, mas agora ele vai trabalhar em conjunto com o arquivo NTX, que contém a posição relativa de cada registro. Fica o seguinte:
REg2 = ALVARO
REg3 = JOSE
Reg1 = XIMENES

18. GO TOP: faz o POINTER pular para o registro 2 = ALVARO
19. SKIP: faz o POINTER pular para o registro 3 = JOSE
20. SKIP: faz o POINTER pular para o registro 1 = XIMENES
21. SKIP -1: faz o POINTER pular para o registro 3 = JOSE
22. GO BOTT: faz o POINTER pular para o registro 1 = XIMESES

Agora, o SEEK (tradução = PROCURAR):
23. SEEK "JOSE": o POINTER vai pular para o registro 3
24. REPLACE NOME WITH "JOSE DA SILVA": vai mudar o conteúdo do registro 3...
25. SEEK "ALVARO": o POINTER vai pro registro 2

Se o arquivo tiver 1.500.000 de registros e o último deles for "XIMENES", se vc fizer SEEK "XIMENES" o POINTER vai pular instantaneamente pra esse registro, e você já pode fazer por exemplo REPLACE NOME WITH "XIMENES SOUZA"

Ao contrário, se vc usar o LOCATE, ocorre o seguinte: o Clipper examina o registro 1. Se não é XIMENES, vai pro registro 2. Idem, vai pro 3... Assim por diante, até chegar no registro número 1.500.000...

Agora, vamos supor que vc mude o nome do "XiMENES" para "ANTONIO XIMENES". O número do registro (FÍSICO) vai continuar 1 mas a ordem vai mudar automaticamente:
REg2 = ALVARO
Reg1 = ANTONIO XIMENES
REg3 = JOSE

Por fim, entra uma função FOUND() = a tradução é "ACHOU", que vc usa junto com o SEEK e as funções EOF() e BOF(). Se vc fizer:

SEEK "ALVARO"
* como existe esse nome, o POINTER vai pro registro 2
* e as funções retornam o seguinte:
?FOUND() -> .T.
?EOF() -> .F.
?BOF() -> .F.

SEEK "XIMENES"
* como não existe mais, o POINTER vai pro EOF
* e as funções retornam o seguinte:
?FOUND() -> .F.
?EOF() -> .T.
?BOF() -> .F.

GO BOTT // vai pro registro JOSE
SKIP // pula pro próximo
* como não tem o próximo...
? EOF() -> .T.

INDEXAÇÂO
No exemplo acima, fiz a indexação só pelo campo NOME. Mas vc pode "misturar" campos no mesmo índice: INDEX ON DTOS(NASC)+NOME -> ordena por data de nascimento e, dentro de cada data, por nome.

Outra coisa: não é preciso fazer a INDEXAÇÂO toda vez que vc abre o arquivo! Você cria o DBF e o INDICE e depois, é só abrir os dois em conjunto: quando vc incluir um registro no DBF, o NTX vai ser atualizado. Mesma coisa na exclusão ou alteração. Veja abaixo em REDE.

Só precisa ficar atento para SEMPRE abrir DBF e NTX em conjunto. Se vc abrir só o DBF e alterar algum registro (que está no indice), da próxima vez que vc abrir o NTX junto vai dar erro (arquivo corrompido).

REDE
Em rede, vc TEM que usar o seguinte:

a) a cláusula EXCLUSIVE
USE CLIENTES NEW EXCLUSIVE
Neste caso, o arquivo ficará de uso exclusivo para você. Ninguém consegue nem visualisar o danado. Esta cláusula é EXIGIDA quando vc faz a iNDEXAÇÂO ou usa os comandos ZAP ou PACK.

b) a cláusula SHARED (compartilhado)
USE CLIENTES NEW SHARED
Neste caso, o arquivo pode ser aberto por mais de um usuário e aí, quando precisar ser feita alguma alteração no DBF, tem que usar o FLOCK() ou o RLOCK().

b.1) FLOCK() = FILE LOCK = Bloqueio do Arquivo: com este comando, o arquivo SHARED continua acessível a todos na rede mas só pode ser alterado por quem conseguiu o comando. É usado quando vc tem que alterar muitos registros e não pode/quer ter mais ninguém mexendo no DBF.

b.1) RLOCK() = RECORD LOCK = Bloqueio do Registro: com este comando, só é bloqueado o REGISTRO onde está o POINTER. Por exemplo, vc está alterando o nome do XIMENES e outro usuário, no mesmo momento, pode estar alterando o nome do ALVARO.

No caso da cláusula EXCLUSIVE, a condição só acaba quando vc fechar o DBF.

No caso do FLOCK() ou RLOCK(), o comando UNLOCK desbloqueia o arquivo ou o registro.

Agora, um exemplo: note que cada programador tem um "jeitão" de trabalhar e existem "n" maneiras de fazer a mesma coisa. Também, o programa vai depender dos objetivos a atingir. Ainda, este exemplo é só uma sequencia de comandos, pra vc ver alguns detalhes. Precisa colocar isso tudo dentro da seu programa.

O IMPORTANTE é vc entender o mecanismo. Depois vc aplica no seu programa. Não use a técnica do COLAR / COPIAR. Via de regra não dá certo... eh eh eh

if (!file("CLIENTES1.NTX") .or. !file("CLIENTES2.NTX"))
  * faz a indexação só se os NTX não existirem
  use clientes new excl // bastam as primeiras 4 letras...
  if neterr()=.t.
    * a função NETERR() retorna .T. se deu erro e .F. se não
    wait "Não deu pra abrir o DBF!"
    quit
  endif
  index on nome to clientes1
  index on prontuario to clientes2
  use
endi
use clientes new shar
if neterr()=.t.
  wait "Não deu pra abrir o DBF!"
  quit
endif
set index to clientes1, clientes2
set orde to 2 // prontuario
set orde to 1 // nome
appe blan
* este comando já bloqueia o novo registro em branco
repl nome with "XIMENES"
repl prontuario with 11
unlock
appe blan
repl nome with "SILVA"
repl prontuario with 22
unlock
seek "XXIMENES"
* não vai achar, certo?
IF !FOUND()
  wait "não achou XXIMENES"
ENDIF
SEEK "XIMENES"
* agora vai achar, mas precisa bloquear o registro.
* note vou vou colocar um CONTADOR de tentativas
* se fizer como vc fez, sem limite, e se algum outro usuario bloqueou o registro
* e esqueceu de sair do programa, vc vai passar o resto do dia parado
* esperando ele sair...
oquei=.f.
@ 24,25 SAY " AGUARDE... "
for conta=1 to 5 // TENTANTIVAS
  if rlock()=.T. 
    oquei=.t.
    EXIT
  ENDI
  inkey(10) // faz uma pausa entre as tentativas
  conta--
next
@ 24,25 SAY "            "
if oquei=.f.
  wait "não consegui bloquear o registro!"
else
  repl nome with "ANTONIO XIMENES"
  dbcommit()
  * veja abaixo
  unlock
endi
* THE END
quit


DBCOMITT() e DBCOMMITALL(): quando vc faz alguma alteração em um DBF (exclusão ou REPLACE), ela pode não ficar visível na hora para toda a rede (o SO pode estar ocupado, cuidando de outras coisas...). Com o DBCOMMIT(), vc força a coisa a acontecer na hora. DBCOMMIT() age só na área de trabalho em foco (a que está SELECT-cionada). DBCOMMITALL() age em todas (ALL = todas).

Bom, escrevi isto tudo meio direto. Pode ser que tenha algum erro.

Se tiver mais dúvidas, buzina.
Avatar de usuário

Eolo
Colaborador

Colaborador
 
Mensagens: 1134
Data de registro: 08 Dez 2005 17:24
Cidade/Estado: São Paulo - SP
Curtiu: 0 vez
Mens.Curtidas: 41 vezes

Re: problema com transferencia de registros dbf

Mensagempor Glauco Cruz Costa » 05 Jun 2009 22:43

Obrigadão, Eolo.
Muita coisa do que vc explicou, eu só recordei.
Meu vôo aqui está sendo em relação ao index.
Vamos ver se eu entendi.


use arquivo shared new
if !file("prontuar.ntx")
do while !flock()
endo
index on prontuar to temp
endif
set index to prontuar

Veja se isto serve.
Então, eu crio o index uma vez. Depois, não preciso criar outra vez, e o set index se encarrega de abri-lo após o use.
É isso mesmo?
Obrigado.
Avatar de usuário

Glauco Cruz Costa
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 102
Data de registro: 15 Dez 2005 21:02
Cidade/Estado: Brasília/DF
Curtiu: 0 vez
Mens.Curtidas: 0 vez

Re: problema com transferencia de registros dbf

Mensagempor Eolo » 05 Jun 2009 23:46

Glauco, chegou perto...

Seguinte: INDEX ON cria os arquivos. SET INDEX abre.

a) pra criar o(s) arquivo(s) indice:
INDEX ON CAMPO TO ARQUIVO.NTX
INDEX ON CAMPO2 TO ARQUIVO2.NTX

b) pra abrir/usar:
USE ARQUIVO[.DBF]
SET INDEX TO ARQUIVO[.NTX],ARQUIVO2[.NTX] // aqui vc está abrindo oS NTX pra trabalhar junto com o DBF

Na criação, o arquivo DBF tem que estar aberto EXCLUSIVE.

Ao invés de
use arquivo shared new
if !file("prontuar.ntx")
do while !flock()
endo
index on prontuar to temp
endif
set index to prontuar


Use o seguinte:
if !file("prontuar.ntx")
  * arquivo NTX não existe
  * então primeiro abre o DBF em modo exclusivo
  use arquivo new exclusive
  if neterr()=.t.
    * deu erro, aborta
    ?"erro ao abrir arquivo DBF"
    quit
  endif
  * DBF aberto em modo exclusivo, então cria o INDICE
  index on prontuar to prontuar[.ntx]
  * agora fecha o DBF em modo exclusivo
  use
endif
* agora abre o DBF em modo compartilhado
use arquivo new shared
if neterr()=.t.
  * deu erro, aborta
  ?"erro ao abrir arquivo DBF"
  quit
endif
* abre o INDICE existente para trabalhar em conjunto com o DBF
set index to prontuar[.ntx]
*etc.


Note que o que está indicado como "[.ntx]" é opcional.
Avatar de usuário

Eolo
Colaborador

Colaborador
 
Mensagens: 1134
Data de registro: 08 Dez 2005 17:24
Cidade/Estado: São Paulo - SP
Curtiu: 0 vez
Mens.Curtidas: 41 vezes

Re: problema com transferencia de registros dbf

Mensagempor Glauco Cruz Costa » 06 Jun 2009 01:17

É que um livro que eu tenho aqui diz que pode tb usar o flock(), ou seja, ou se abre o dbf em com use exclusive ou bloqueia-o com flock().
Então, não dá mesmo certo bloqueá-lo com flock()?

Bom, é claro que eu esqueci de dar um unlock para desbloquá-lo.
Veja agora:

use arquivo shared new // abro o arquivo dbf compartilhado
if !file("prontuar.ntx") // testo se existe não existe o ntx
do while !flock() // ao verificar que nao existe o ntx, tento bloquear o dbf
endo
index on prontuar to temp // após bloquear o dbf, eu indexo
endif
unlock // depois, desbloqueio o dbf
set index to prontuar // aqui, abro o ntx
Avatar de usuário

Glauco Cruz Costa
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 102
Data de registro: 15 Dez 2005 21:02
Cidade/Estado: Brasília/DF
Curtiu: 0 vez
Mens.Curtidas: 0 vez

Re: problema com transferencia de registros dbf

Mensagempor Eolo » 06 Jun 2009 08:38

Até onde eu sei, vai dar erro. Pelo seguinte: o comando INDEX tenta criar o arquivo NTX em modo exclusivo. Então, se já tem um outro usuário com o mesmo DBF + NTX abertos (SHARED), o INDEX não vai conseguir a exclusividade e o seu programa vai abortar.

Independente disso, eu penso o seguinte: se eu vou criar ou recriar o arquivo XPTO.NTX, por que motivo eu aceitaria que um outro usuario estivesse usando o mesmo XPTO.NTX que vai ser substituido? Não faz sentido. Em outras palavras: pra indexar, tem que ter acesso EXCLUSIVO.

Precisa também usar o NETERR(), pra ver se o USE deu certo. Se o USE não funcionar, por alguma razão, o seu programa vai abortar na criação do NTX...

Você fez "index on prontuar to temp" e depois "set index to prontuar". Tem que ser "set index to temp" (sendo TEMP o nome do arquivo NTX.

Então:

if !file("prontuar.ntx")          // se não existe existe o ntx
  use arquivo exclusive new        // tenta abrir o arquivo dbf exclusive
  if neterr()                     // se deu erro..
     ? "erro"
     return
  endi
  index on prontuar to temp       // indexa
endi
use arquivo shared              // aqui muda de exclusive pra shared
set index to temp               // aqui, abre o ntx


COMPLEMENTANDO: o USE EXCLUSIVE e o FLOCK(), embora bloqueiem o DBF, são diferentes. O primeiro faz com que ninguém mais na rede consiga nem ao menos abrir o DBF: ele fica EXCLUSIVO de quem o abriu. Já o FLOCK(), que vem em conjunto com um USE SHARED, permite que outros usuários acessem o DBF, mas somente para leitura.
Avatar de usuário

Eolo
Colaborador

Colaborador
 
Mensagens: 1134
Data de registro: 08 Dez 2005 17:24
Cidade/Estado: São Paulo - SP
Curtiu: 0 vez
Mens.Curtidas: 41 vezes

Re: problema com transferencia de registros dbf

Mensagempor Glauco Cruz Costa » 06 Jun 2009 13:29

Ao invés de

if neterr()=.t.

eu poderia usar

do while .t.
use arquivo new exclusive
if neterr() = .t.
exit
else
loop
endif
endo

para esperar que dê certo a abertura do arquivo?
Avatar de usuário

Glauco Cruz Costa
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 102
Data de registro: 15 Dez 2005 21:02
Cidade/Estado: Brasília/DF
Curtiu: 0 vez
Mens.Curtidas: 0 vez

Próximo



Retornar para CA-Clipper

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 11 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro