DELETE ALL em arquivos indexados com cláusula !DELETED()

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

Avatar do usuário
carlaoonline
Usuário Nível 3
Usuário Nível 3
Mensagens: 190
Registrado em: 24 Ago 2014 22:38
Localização: Porto Alegre-RS

DELETE ALL em arquivos indexados com cláusula !DELETED()

Mensagem por carlaoonline »

Bom dia!

Para que o OrdKeyCount() me mostre sempre a quantidade real de registros apresentado nos browses, em meu sistema uso a cláusula "FOR !DELETED()" em todos meus índices.


O problema é que percebi que o "DELETE ALL FOR condições..." NAO FUNCIONA com a condição "FOR !DELETED()"

Código: Selecionar todos


// hbmk2.exe z_prog -b


Function Main()


SET DELETED ON     
SETMODE(25,80)
SET COLOR TO ("W+/B")
CLS

Alert("Vai iniciar!")

// Criando um banco de dados
If !File("fat_discri.dbf")
   aStructure := {}
   aAdd( aStructure, { "PEDIDO"    , "N",   7,  1 })
   aAdd( aStructure, { "DESCRICAO" , "C",  40,  0 })
   aAdd( aStructure, { "QUANT"     , "N",  10,  2 })
   aAdd( aStructure, { "UNIT"      , "N",  12,  2 })
   aAdd( aStructure, { "TOTAL"     , "N",  14,  2 })
   aAdd( aStructure, { "LINHA"     , "N",   2,  0 })
   dbCreate("fat_discri.dbf", aStructure)
EndIf


USE FAT_DISCRI 
COPY TO TESTE
USE TESTE NEW EXCLU

// Incluindo 14 registros no banco de dados
    FOR F=1 TO 14  
        APPEND BLANK
        REPLACE DESCRICAO WITH "Linha -> "+str(f)
        REPLACE LINHA WITH F
    NEXT

INDEX ON LINHA TAG LINHA TO TESTE FOR !DELETED()

    alert("Apos indexar, o arquivo "+alias()+" possui "+alltrim(str(ordkeycount()))+" registros validos.")
    dbedit()
    cls
        
    DELETE ALL FOR RECNO()>4 // -> DELETA APENAS 1 REGISTRO
    alert("Depois de TENTAR deletar 10 registros, o arquivo "+alias()+" possui "+alltrim(str(ordkeycount()))+" registros validos.")
    dbedit()
    cls

    GO TOP  
    DELETE ALL FOR LINHA>4  // CONTINUA DELETANDO APENAS MAIS 1 REGISTRO  
    REINDEX  
    COUNT TO nTotalNaoDeletados FOR !DELETED()  // Nem precisaria o "FOR !DELETED()" ...

    alert("Depois de MAIS UMA TENTATIVA de deletar, o arquivo "+alias()+" possui "+alltrim(str(nTotalNaoDeletados))+" registros validos.")
    dbedit()
    cls

QUIT


No código acima só funciona se tirar o "FOR !DELETED()" da indexação, mas nesse caso o OrdKeyCount() contabiliza os deletados.

Vejo que a solução é sempre abrir o arquivo sem índice antes de um DELE ALL, mas no caso de arquivo com 500 mil registros fica meio na contramão...

Analisando o resultado do código acima, acredito que o comando DELETE ALL deleta e atualiza o índice UM a UM ao invés de deletar UM a UM a DEPOIS atualizar o índice pelo lote deletado, ou seja, na primeira deleção já quebra o índice pois sendo um DELETADO se perde no loop.

É assim mesmo ou tem algum macete ?


Grato!
Avatar do usuário
vailton
Colaborador
Colaborador
Mensagens: 390
Registrado em: 17 Nov 2005 19:08
Localização: Brasil
Contato:

DELETE ALL em arquivos indexados com cláusula !DELETED()

Mensagem por vailton »

Olá,

Deixe-me ver se entendi o caso e consigo contribuir:

1) Abra o arquivo com todos os indices
2) dê um SET ORDER TO 0
3) Use o seu comando DELETE ALL ...
4) Volte para a ORDER necessária.

Creio que isto deve te ajudar.
Vailton Renato
"No dia mais claro, na noite mais escura... o bug sucumbirá ante a minha presença"

E-mail/MSN: contato@vailton.com.br
Skype: vailtom
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

DELETE ALL em arquivos indexados com cláusula !DELETED()

Mensagem por JoséQuintas »

carlaoonline escreveu:Vejo que a solução é sempre abrir o arquivo sem índice antes de um DELE ALL, mas no caso de arquivo com 500 mil registros fica meio na contramão...
Não vejo situação pra usar DELETE ALL.
Se está apagando anterior a uma data, use um índice pela data.

Aliás... criando rotina tem mais controle sobre o resultado, por exemplo, pra não travar a janela e o Windows querer fechar com a mensagem: este programa não está respondendo.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
carlaoonline
Usuário Nível 3
Usuário Nível 3
Mensagens: 190
Registrado em: 24 Ago 2014 22:38
Localização: Porto Alegre-RS

DELETE ALL em arquivos indexados com cláusula !DELETED()

Mensagem por carlaoonline »

Grato a todos pelo apoio.
JoséQuintas escreveu:Não vejo situação pra usar DELETE ALL.
Se está apagando anterior a uma data, use um índice pela data.
É um banco de dados com milhares de registros de cobrança (tipo essas empresas de tele marketing que ficam ligando e cobrando), assim que a cobrança é acertada, recebida, conferida e quitada, ela é marcada como finalizada e ao final de cada mês elas são copiadas para outra base de dados e DELETADAS da base principal. Uma vez que já foram resolvidas, não tem mais sentido estarem ali pesando o arquivo principal, nesse caso, se faz necessário o DELE ALL.


vailton escreveu:2) dê um SET ORDER TO 0
Dessa forma deleta e mantém os índices atualizados, isso é ótimo, a única questão é que não aceita um OrdScope, e em arquivos muito grandes e em rede fica mais rápido o uso de uma função para apagar um a um dentro do escopo escolhido (mais ou menos o que sugeriu o Quintas).

Certo que hoje em dia as máquinas e as redes são tão rápidas que muitas funções e procedimentos que eram feitos pra otimizar tempo, memória e armazenamento na época do Summer 87 e 5.2 (por exemplo) ficaram obsoletos a algum tempo e "praticamente" de qualquer forma que se fizer teremos o resultado em tempos semelhantes.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

DELETE ALL em arquivos indexados com cláusula !DELETED()

Mensagem por Itamar M. Lins Jr. »

Olá!
Pode usar o ordscope.
Use, DO WHILE datax etc... meualiasdbf->(!eof())... delete ...skip(), dentro do ordscope.

Pq quando apaga vai sempre para o primeiro.

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

DELETE ALL em arquivos indexados com cláusula !DELETED()

Mensagem por Itamar M. Lins Jr. »

Ola!
Pode inclusive indexar pegando o recno() do registro a ser deletado... usando temporary... jogar em array etc... e depois ir dando FOR NEXT DbGoTo(nArrayRec[n]) delete...
Que será rápido, pois só vai pegar os registros recno() que serão deletados.
Resumindo, é não usar DELETE ALL... pois varre o DBF todo, e COUNT, SUM... eu não uso esses comandos. Filtro o que desejo e faço o quer for preciso usando DO WHILE pois respeita o ORDSCOPE, INDEX TEMPORARY...

Saudações,
Itamar M. Lins Jr.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

DELETE ALL em arquivos indexados com cláusula !DELETED()

Mensagem por JoséQuintas »

carlaoonline escreveu:Certo que hoje em dia as máquinas e as redes são tão rápidas que muitas funções e procedimentos que eram feitos pra otimizar tempo, memória e armazenamento na época do Summer 87 e 5.2 (por exemplo) ficaram obsoletos a algum tempo e "praticamente" de qualquer forma que se fizer teremos o resultado em tempos semelhantes.
Continua tudo valendo.
Se for SQL, é enviar o comando e nem precisa esperar o resultado, mas mesmo assim, é tentar otimizar o tempo de processamento.
carlaoonline escreveu:ssim que a cobrança é acertada, recebida, conferida e quitada, ela é marcada como finalizada e ao final de cada mês elas são copiadas para outra base de dados e DELETADAS da base principal. Uma vez que já foram resolvidas, não tem mais sentido estarem ali pesando o arquivo principal, nesse caso, se faz necessário o DELE ALL.
Salve a data de finalização, e utilize como índice.
Também pode utilizar o índice pra criar um sub-índice e aí faz o que disse no começo sobre o que iria usar pra contagem.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Responder