* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Novembre 23, 2024, 11:41:17 pm

Inserisci il nome utente, la password e la durata della sessione.

108 Visitatori, 0 Utenti

Autore Topic: [Risolto] Controllo integrità database  (Letto 1745 volte)

petrusic

  • Hero Member
  • *****
  • Post: 624
  • Karma: +0/-0
[Risolto] Controllo integrità database
« il: Gennaio 19, 2024, 04:58:38 pm »
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:
Codice: [Seleziona]
 . . .
//---------------------- 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?
« Ultima modifica: Gennaio 22, 2024, 09:18:16 am da petrusic »
ciao ciao

giacomarko

  • Full Member
  • ***
  • Post: 107
  • Karma: +6/-0
Re:Controllo integrità database
« Risposta #1 il: Gennaio 19, 2024, 06:09:39 pm »
quesito interessante,

chiaramente hai affrontato il problema in modo lineare, niente da dire, probabilmente avrei fatto lo stesso

ad ogni modo, dato che migliorare si può sempre... ;-)

non e chiaro quale DB usi, ma dipendentemente da questo, ci potrebbero essere funzioni interne inerenti al DB, che potrebbero darti le info che chiedi con una unica query,

a pelle direi che la soluzione dovrebbe essere quella di spostare la ricerca, lato DB

in MySQL con la keyword UNION, potresti ottenere quello che cerchi in un unica esecuzione, ammesso che il tuo DB lo contempli

prova a verificare quì

https://www.google.com/amp/s/rosariociaglia.altervista.org/mysql-come-contare-le-righe-di-una-o-piu-tabelle/amp/

SO: W11
Release Lazarus: 3.0 del 2023.12.17 win32/win64
Versione FPC: 3.2.2
DB: MySQL 5.0, MSAccess

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1399
  • Karma: +44/-0
  • Prima ascoltare, poi decidere
Re:Controllo integrità database
« Risposta #2 il: Gennaio 19, 2024, 09:01:43 pm »
Vado così a memoria, ma su una ZTable ci dovrebbe essere la proprietà RecordCount ....

Se usi le tabelle, oltre alle query, hai già il numero di record.

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

giacomarko

  • Full Member
  • ***
  • Post: 107
  • Karma: +6/-0
Re:Controllo integrità database
« Risposta #3 il: Gennaio 20, 2024, 12:07:29 am »
ricordi bene,

anche se alla fine o con una query o interrogando direttamente i dataset, alla fine fai la stessa cosa, chiedi quanti record ci sono ad ogni singola tabella...

bisognerebbe imbastire un test e misurare i tempi via SQL vs i tempi via dataset...

se la funzione UNION gira, fai tutto in un colpo, con un unico accesso
SO: W11
Release Lazarus: 3.0 del 2023.12.17 win32/win64
Versione FPC: 3.2.2
DB: MySQL 5.0, MSAccess

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2921
  • Karma: +20/-4
Re:Controllo integrità database
« Risposta #4 il: Gennaio 20, 2024, 10:44:38 am »
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

Codice: [Seleziona]
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
« Ultima modifica: Gennaio 20, 2024, 10:48:30 am da nomorelogic »
Imagination is more important than knowledge (A.Einstein)

petrusic

  • Hero Member
  • *****
  • Post: 624
  • Karma: +0/-0
Re:Controllo integrità database
« Risposta #5 il: Gennaio 20, 2024, 05:24:36 pm »
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
Codice: [Seleziona]
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.

Codice: [Seleziona]
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.
ciao ciao

bonmario

  • Hero Member
  • *****
  • Post: 1360
  • Karma: +11/-1
Re:Controllo integrità database
« Risposta #6 il: Gennaio 20, 2024, 05:31:21 pm »
Codice: [Seleziona]
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
Codice: [Seleziona]
  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

petrusic

  • Hero Member
  • *****
  • Post: 624
  • Karma: +0/-0
Re:Controllo integrità database
« Risposta #7 il: Gennaio 20, 2024, 07:42:21 pm »
Codice: [Seleziona]
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
Codice: [Seleziona]
  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:
Codice: [Seleziona]
 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
Citazione
sql= |select * from (select "causalifreq" AS nomeTbx, count(*) AS conta from causalifreq UNION select "componfam" as nomeTbx, count(*) AS conta from componfam) AS contarec|
ciao ciao

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2921
  • Karma: +20/-4
Re:Controllo integrità database
« Risposta #8 il: Gennaio 20, 2024, 11:50:28 pm »
l'sql usa l'apice singolo per delimitare le stringhe e non il doppio apice
per questo il risultato della writeln deve essere:
Codice: [Seleziona]
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
Codice: [Seleziona]
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';

« Ultima modifica: Gennaio 20, 2024, 11:54:02 pm da nomorelogic »
Imagination is more important than knowledge (A.Einstein)

petrusic

  • Hero Member
  • *****
  • Post: 624
  • Karma: +0/-0
Re:Controllo integrità database
« Risposta #9 il: Gennaio 21, 2024, 10:13:50 am »
l'sql usa l'apice singolo per delimitare le stringhe e non il doppio apice
per questo il risultato della writeln deve essere:
Codice: [Seleziona]
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

Purtroppo devo dirti che le prove fatte prima di postare hanno dimostrato che lo SQL non si arrabbia di fronte al doppio apice. Allego un'ulteriore prova fatta stamani in DB-Browser. Come puoi vedere, NON da' Errore.

Comunque, siccome bisogna percorrere tutte le strade possibili, fino a trovare quella giusta, ho provato anche a mettere i 2 apici singoli dentro la stringa sql: Ebbene, NON hanno funzionato, nè DB-Browser, nè Lazarus.

ciao ciao

petrusic

  • Hero Member
  • *****
  • Post: 624
  • Karma: +0/-0
Re:Controllo integrità database
« Risposta #10 il: Gennaio 21, 2024, 03:51:45 pm »
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:
Codice: [Seleziona]
DataModule1.ZConnection1.Database:= dbCorr;
DataModule1.ZConnection1.Connected:= True; 

Dopo avere impostato correttamente le suddette istruzioni, ho ripetuto la query suggerita da nomorelogic :
Codice: [Seleziona]
  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 :
Codice: [Seleziona]
  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.
ciao ciao

petrusic

  • Hero Member
  • *****
  • Post: 624
  • Karma: +0/-0
Re:Controllo integrità database
« Risposta #11 il: Gennaio 21, 2024, 04:14:17 pm »
Ho capito perchè non funzionava.
Ho inserito l'inizializzazione dell'indice dell'array ed ecco il risultato:
Citazione
tbDBintegro[0, 0]= "causalifreq"
tbDBintegro[0, 1]= "570"
tbDBintegro[1, 0]= "componfam"
tbDBintegro[1, 1]= "6"
tbDBintegro[2, 0]= "ggaperte"
tbDBintegro[2, 1]= "64"
tbDBintegro[3, 0]= "movimgg"
tbDBintegro[3, 1]= "66547"
tbDBintegro[4, 0]= "prestmom"

Mi pare un bellissimo risultato. Mi dispiace solo non aver capito prima cosa mancava a Zeos per non potere eseguire la query Union.

Avrei risparmiato anche voi tutti.

Grazie ancora  ;D
ciao ciao

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2921
  • Karma: +20/-4
Re:[Risolto] Controllo integrità database
« Risposta #12 il: Gennaio 22, 2024, 09:29:55 am »
ottimo risultato
puoi dirci qualcosa sui tempi di esecuzione?
Imagination is more important than knowledge (A.Einstein)

petrusic

  • Hero Member
  • *****
  • Post: 624
  • Karma: +0/-0
Re:[Risolto] Controllo integrità database
« Risposta #13 il: Gennaio 22, 2024, 03:46:52 pm »
ottimo risultato
puoi dirci qualcosa sui tempi di esecuzione?
Non c'è dubbio che è tutta un'altra cosa.
Il caricamento nella tabella di memoria avviene all'istante.
 ;)
ciao ciao

 

Recenti

How To

Utenti
  • Utenti in totale: 803
  • Latest: maXim.FI
Stats
  • Post in totale: 19180
  • Topic in totale: 2288
  • Online Today: 117
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 108
Total: 108

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.