Página 1 de 1

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

Enviado: 05 Abr 2022 09:11
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!

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

Enviado: 05 Abr 2022 10:43
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.

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

Enviado: 05 Abr 2022 12:28
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.

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

Enviado: 05 Abr 2022 17:44
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.

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

Enviado: 05 Abr 2022 18:20
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.

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

Enviado: 05 Abr 2022 18:25
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.

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

Enviado: 05 Abr 2022 20:52
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.