Per motivi di sicurezza, su cui non mi dilungo, per non tediarvi, ho bisogno di rivedere una mia funzione che mi permette di conoscere, con esattezza. quanti record contiene ciascuna tabella del DB.
Attualmente acquisisco i suddetti valori con le seguenti istruzioni:
. . .
//---------------------- Estrazione Totale n. record di ciascuna Tabella del DB -------------------------------------------------------------------
Edit7.Text:= IntToStr(numElem);
numElem:= ContaRecDbTbX('piancont');
Edit16.Text:= IntToStr(numElem);
numElem:= ContaRecDbTbX('causalifreq');
Edit10.Text:= IntToStr(numElem);
numElem:= ContaRecDbTbX('ggaperte');
Edit11.Text:= IntToStr(numElem);
numElem:= ContaRecDbTbX('movimgg');
Edit12.Text:= IntToStr(numElem);
numElem:= ContaRecDbTbX('partmovv');
Edit13.Text:= IntToStr(numElem);
numElem:= ContaRecDbTbX('prestmom');
Edit14.Text:= IntToStr(numElem);
numElem:= ContaRecDbTbX('racodvoci');
Edit15.Text:= IntToStr(numElem);
numElem:= ContaRecDbTbX('restacassagg');
Edit17.Text:= IntToStr(numElem);
numElem:= ContaRecDbTbX('riepmovg');
Edit18.Text:= IntToStr(numElem);
numElem:= ContaRecDbTbX('componfam');
Label4.Caption:= IntToStr(numElem);
numElem:= ContaRecDbTbX('riepnewrecdb');
Label5.Caption:= IntToStr(numElem);
. . .
function ContaRecDbTbX(nomeTabDb: String): Integer;
var
totRecQry: Integer;
dtPrec, striMia, sql: String;
begin
//----------- Open del DB ------------------------------------------------------
sql:= 'SELECT * FROM ' + nomeTabDb;
DataModule1.ZReadOnlyQuery1.Active:= False;
DataModule1.ZReadOnlyQuery1.SQL.Text:= sql;
DataModule1.ZReadOnlyQuery1.Active:= True;
totRecQry:= DataModule1.ZReadOnlyQuery1.RecordCount;
Result:= totRecQry;
end;
//-------------------------------------------------------------------
Come si può vedere qui sopra, eseguo ben 11 volte l'accesso alla function che mi permette di ricavare i numeri che mi occorrono.
Ormai, funziona da diverso tempo, ma mi costa, in termini di tempo più di 7 secondi.
Mi pare pesante. Sicuramente sono io che non so sfruttare al meglio le qualità di Lazarus Free Pascal.
Vorrei perciò mettere in pratica un metodo che duri al massimo un battito di ciglia. E' possibile, che qualcuno sappia come?
penso che il modo più veloce sia quello di chiedere direttamente al database in un unico colpo (come suggerito da giacomarko)
prova ad eseguire questa query sul db, è abbastanza standard e dovrebbe funzionare ovunque
quando ti funziona eseguila da Lazarus
sono convinto che la velocità di esecuzione sarà la migliore possibile
select * from (
select 'tabella1' as nome, count(*) as conta from tabella1
union
select 'tabella2' as nome, count(*) as conta from tabella2
union
select 'tabella3' as nome, count(*) as conta from tabella3
union
select 'tabella4' as nome, count(*) as conta from tabella4
) as contarecord
nomorelogic
Edit:
sul alcuni server forse devi sostituire "union" con "union all"
da provare
non e chiaro quale DB usi.
Hai ragione. L'avevo indicato, ma nel correggere il contenuto, l'ho cancellato, involontariamente.
Io uso SQLite3, l'unico che conosco un pò.
penso che il modo più veloce sia quello di chiedere direttamente al database in un unico colpo (come suggerito da giacomarko)
prova ad eseguire questa query sul db, è abbastanza standard e dovrebbe funzionare ovunque
quando ti funziona eseguila da Lazarus
select * from (
select 'tabella1' as nome, count(*) as conta from tabella1
union
select 'tabella2' as nome, count(*) as conta from tabella2
union
select 'tabella3' as nome, count(*) as conta from tabella3
union
select 'tabella4' as nome, count(*) as conta from tabella4
) as contarecord
Ho provato la query in DB-BRowser e funziona.
L'ho provata, poi in Lazarus, ma non funziona. L'ho ridotta anche ad una sola riga, ma non funziona lo stesso.
sql:= 'select * from (select "causalifreq" AS nomeTbx, count(*) as conta from causalifreq';
sql:= sql + 'UNION select "componfam" as nomeTbx, count(*) as conta from componfam) as contarec';
DataModule1.ZReadOnlyQuery1.Active:= False;
DataModule1.ZReadOnlyQuery1.SQL.Text:= sql;
DataModule1.ZReadOnlyQuery1.Active:= True; <------ quando viene eseguita questa istruzione da' "ERRORE LOGICO"
DataModule1.ZReadOnlyQuery1.First;
while not DataModule1.ZReadOnlyQuery1.EOF do
Ho provato, infine, a disattivare la riga, ma produce un Errore per Dataset inattivo.
sql:= 'select * from (select "causalifreq" AS nomeTbx, count(*) as conta from causalifreq';
sql:= sql + 'UNION select "componfam" as nomeTbx, count(*) as conta from componfam) as contarec';
La seconda riga, deve diventare
sql:= sql + ' ' + 'UNION select "componfam" as nomeTbx, count(*) as conta from componfam) as contarec';
In pratica, devi mettere uno spazio prima di "union".
Così come hai fatto tu, la parola "causalifreq" della riga precedente, la stai attaccando alla parola "union" della riga successiva, ed ottieni "causalifreqUNION" tutto attaccato !!
Ciao, Mario
sql:= 'select * from (select "causalifreq" AS nomeTbx, count(*) as conta from causalifreq';
sql:= sql + 'UNION select "componfam" as nomeTbx, count(*) as conta from componfam) as contarec';
La seconda riga, deve diventare
sql:= sql + ' ' + 'UNION select "componfam" as nomeTbx, count(*) as conta from componfam) as contarec';
In pratica, devi mettere uno spazio prima di "union".
Così come hai fatto tu, la parola "causalifreq" della riga precedente, la stai attaccando alla parola "union" della riga successiva, ed ottieni "causalifreqUNION" tutto attaccato !!
Ciao, Mario
Grazie Mario. Hai ragione, mi era sfuggito. L'ho modificata, ma non funziona lo stesso. C'è un errore di sintassi che io NON riesco a capire.
Ecco le righe con la correzione che mi hai suggerito:
sql:= 'select * from (select "causalifreq" AS nomeTbx, count(*) AS conta from causalifreq';
sql:= sql + ' UNION select "componfam" as nomeTbx, count(*) AS conta from componfam) AS contarec';
WriteLn('sql= |' + sql + '|');
DataModule1.ZReadOnlyQuery1.Active:= False;
DataModule1.ZReadOnlyQuery1.SQL.Text:= sql;
DataModule1.ZReadOnlyQuery1.Active:= True;
Per mia tranquillità, riporto anche l'ìesito del comando
sql= |select * from (select "causalifreq" AS nomeTbx, count(*) AS conta from causalifreq UNION select "componfam" as nomeTbx, count(*) AS conta from componfam) AS contarec|
l'sql usa l'apice singolo per delimitare le stringhe e non il doppio apice
per questo il risultato della writeln deve essere:
sql= |select * from (select 'causalifreq' AS nomeTbx, count(*) AS conta from causalifreq UNION select 'componfam' as nomeTbx, count(*) AS conta from componfam) AS contarec|
per ottenere un apice singolo in una stringa pascal bisogna fare l'escape con un altro apice singolo
se usi questa stringa su DB-BRowser vedrai che funziona mentre quella che pai postato tu (con il doppio apice), ti darà errore
ora non riesco a provare ma le istruzioni seguenti dovrebbero essere corrette
notare che solo select ci sono 2 apici singoli e non un doppio apice
e così anche a seguire
sql:= 'select * from (select ''causalifreq'' AS nomeTbx, count(*) AS conta from causalifreq';
sql:= sql + ' UNION select ''componfam'' as nomeTbx, count(*) AS conta from componfam) AS contarec';
Allora, ho fatto un buon passo avanti.
Ho rivisto le istruzioni inserite e mi sono ricordato che, dopo avere stabilito quale database cosiderare come DB corrente, devo dare a Zeos l'indirizzo del DB ed attivarne la connessione.
Poichè il controllo che ho inserito va posto a, monte, prima di qualsiasi altra operazione sul DB, avrei dovuto spostare anche le istruzioni:
DataModule1.ZConnection1.Database:= dbCorr;
DataModule1.ZConnection1.Connected:= True;
Dopo avere impostato correttamente le suddette istruzioni, ho ripetuto la query suggerita da nomorelogic :
sql:= 'select * from (select "causalifreq" AS nomeTbx, count(*) AS conta from causalifreq';
sql:= sql + ' UNION select "componfam" as nomeTbx, count(*) AS conta from componfam';
sql:= sql + ' UNION select "ggaperte" as nomeTbx, count(*) as conta from ggaperte';
sql:= sql + ' UNION select "movimgg" as nomeTbx, count(*) as conta from movimgg) AS contarec';
e, con soddisfazione, ho visto che l'errore è finalmente scomparso.
Mi resta ancora di farmi restituire da Zeos i totali delle singole tabelle.
Pensando che potessi comportarmi come quando estraggo il contenuto mdi un campo del DB, ho scritto di brutta :
i:= 0;
sql:= 'select * from (select "causalifreq" AS nomeTbx, count(*) AS conta from causalifreq';
sql:= sql + ' UNION select "componfam" as nomeTbx, count(*) AS conta from componfam';
sql:= sql + ' UNION select "ggaperte" as nomeTbx, count(*) as conta from ggaperte';
sql:= sql + ' UNION select "movimgg" as nomeTbx, count(*) as conta from movimgg) AS contarec';
DataModule1.ZReadOnlyQuery1.Active:= False;
DataModule1.ZReadOnlyQuery1.SQL.Text:= sql;
DataModule1.ZReadOnlyQuery1.Active:= True;
DataModule1.ZReadOnlyQuery1.First;
while not DataModule1.ZReadOnlyQuery1.EOF do
begin
tbDBintegro[i, 1]:= DataModule1.ZReadOnlyQuery1.FieldByName('conta').AsString;
DataModule1.ZReadOnlyQuery1.Next;
i:= i + 1;
end;
Come mi aspettavo, si è manifestato un nuovo Errore, ma, pur avendo cercato, non ho trovato l'esempio che mi riguarda.