Page 1 of 1
Copy structure or create new file dbf
Posted: Tue Jun 07, 2022 11:33 am
by Silvio.Falconi
to facilitate viewing, since I have too large an archive I decided to create a configuration to create another smaller archive
maybe if I had a smaller database the procedures could work better and faster
i tried inTdatabase
oLotto:CopyTo( cDir+"Integrale")
oLotto:CopyTo( cDir+"Virtuale")
but this makes a physical copy of the dbf, instead I wanted to create at least for the "Virtual" archive only the structure and then through a filtering system insert the selected records in the new archive
How could I do ?
Code: Select all | Expand
If nTipo=2
oDbf :=TDatabase():Open( , cDir+"Virtuale", "DBFCDX", .T. )
oDbf:setorder(1)
oDbf:Exec( <||
SET FILTER TO ( dFirst <= FIELD->DATA .AND. ;
dLast >= FIELD->DATA )
return nil
> )
oDbf:gobottom()
else
oDbf :=TDatabase():Open( , cDir+"Integrale", "DBFCDX", .T. )
oDbf:setorder(1)
oDbf:gobottom()
Endif
If I use
oDbf:Exec( <||
SET FILTER TO ( dFirst <= FIELD->DATA .AND. ;
dLast >= FIELD->DATA )
return nil
> )
then something not run
that's why I thought about creating a new archive by filtering from the full archive
Re: Copy structure or create new file dbf
Posted: Tue Jun 07, 2022 1:10 pm
by nageswaragunupudi
Re: Copy structure or create new file dbf
Posted: Wed Jun 08, 2022 7:51 pm
by James Bott
Using an index with a scope is much faster.
You create the index once when the database is first used, then you automatically open the index whenever the database object is opened. Then you set the scope and then the low and high values you want to see using oDB:setScope(xLow,xHigh). The only records read will be those you want.
I tested a 1 million record DBF file using a scope to filter out about 20,000 records and it takes less than a second! Using a filter instead takes 23 seconds.
Re: Copy structure or create new file dbf
Posted: Wed Jun 08, 2022 8:02 pm
by Marc Venken
James, This is what you mean ? or a other way ?
Best to have the index set to the index of the field ?
Code: Select all | Expand
// oBrw[2]:bChange := { || Scope("factinfo","document","factart","factart"),oBrw22:refresh() }
function Scope(cParent,cData,cChild,cChildTag)
LOCAL cZoekdata:= alltrim(upper( (cParent)->&cData))
(cChild)->(dbsetorder(cChildTag))
(cChild)->(ORDSCOPE(0, "" ) ) // these 2 lines seems to be best used to clear the scope ? Is this still needed ?
(cChild)->(ORDSCOPE(1, "" ) )
(cChild)->( ORDSCOPE(0, cZoekData ) )
(cChild)->(ORDSCOPE(1, cZoekData ) )
(cChild)->(DBGOTOP())
Return NIL
Re: Copy structure or create new file dbf
Posted: Thu Jun 09, 2022 4:01 am
by Jimmy
hi Silvio,
are you sure that you want Dates EXECPT "Filter"
that only work for
"normal" i want Dates between "Filter"-Top / -End
---
Code: Select all | Expand
USE XXX
COPY STRUCTURE [FIELDS <cFieldname,...>] TO <cFilename>
to create a EMPTY() new DBF
Re: Copy structure or create new file dbf
Posted: Thu Jun 09, 2022 7:42 am
by Silvio.Falconi
YesterDay I made as I made on Clipper
Before i create two Database
Create_VirtualeDb(cdir)
Create_IntegraleDb(cDir)
then
oLotto:=TDatabase():Open( , cDir+"lotto", "DBFCDX", .T. )
oLotto:setorder(1)
oLotto:Exec( <||
SET FILTER TO ( dFirst <= FIELD->DATA .AND. ;
dLast >= FIELD->DATA .AND. ;
aCountMesi[ MONTH( FIELD->DATA ) ] .AND. ;
aCountGiorni[ DOW( FIELD->DATA ) ] .AND. ;
aCountDate[ DAY( FIELD->DATA ) ] )
return nil
> )
oLotto:gobottom()
If nTipo=2
atempDbf:= oLotto:DbfToArray()
oVirtuale:=TDatabase():Open( , cDir+"Virtuale", "DBFCDX", .T. )
oVirtuale:SetOrder( 0 )
oVirtuale:ArrayToDBF( atempDbf, , nil, .t., .t. )
oVirtuale:close()
else
oLotto:gobottom()
atempDbf:= oLotto:DbfToArray()
oIntegrale:=TDatabase():Open( , cDir+"Integrale", "DBFCDX", .T. )
oIntegrale:SetOrder( 0 )
oIntegrale:ArrayToDBF( atempDbf, , nil, .t., .t. )
oIntegrale:close()
Endif
oLotto:close()
For Now it seems to run ok
Re: Copy structure or create new file dbf
Posted: Thu Jun 09, 2022 10:11 am
by Marc Venken
Silvio,
You have it running... That's mostly the goal ....
But did you try the scope ? I would think it should be faster and less code. A new second filtering (maybe not needed) would also be faster.
Mostly out of interest this question.
Re: Copy structure or create new file dbf
Posted: Thu Jun 09, 2022 11:42 am
by Silvio.Falconi
Marc Venken wrote:Silvio,
You have it running... That's mostly the goal ....
But did you try the scope ? I would think it should be faster and less code. A new second filtering (maybe not needed) would also be faster.
Mostly out of interest this question.
I don't really trust the ...scope
then Nages told me to use the filter
also because I have to filter many elements
- the months
- the days of the week
- the numbers of the month
- the monthly indices (which I have not entered for now)
all these data are stored in arrays with .t. or with .f.
so I tried as Nages suggested
Code: Select all | Expand
oLotto:Exec( <||
SET FILTER TO ( dFirst <= FIELD->DATA .AND. ;
dLast >= FIELD->DATA .AND. ;
aCountMesi[ MONTH( FIELD->DATA ) ] .AND. ;
aCountGiorni[ DOW( FIELD->DATA ) ] .AND. ;
aCountDate[ DAY( FIELD->DATA ) ] )
return nil
> )
it seems to be working fine for now
Re: Copy structure or create new file dbf
Posted: Thu Jun 09, 2022 7:19 pm
by James Bott
Marc,
James, This is what you mean ? or a other way ?
Best to have the index set to the index of the field ?
Yes, but I would do this:
Save the current recno()
If they exist, save the database's state (current index and the top and bottom scopes and the current recordNo()).
set the index and scopes you need to use.
Do a gotop().
Do whatever...
Then at the end of the routine, restore the database's state (the old index and recno() and the old scopes (if they exist).
Another option is to open a new copy of the needed database within your routine. Then you don't have to worry about saving and restoring the database's state. But you do need to close the local copy of the database at the end of your routine.