Italian community of Lazarus and Free Pascal

Programmazione => Databases => Topic aperto da: Maxx - Marzo 28, 2018, 12:07:35 am

Titolo: [Risolto] Query di delete su più tabelle
Inserito da: Maxx - Marzo 28, 2018, 12:07:35 am
Buonasera.

Ho un problemino che non riesco a risolvere.

Dovendo cancellare da più tabelle diverse, e non volendo aprire e chiudere continuamente la transazione (è all'interno di un ciclo piuttosto oneroso) ho creato una query fatta:

ModDati.Qry_Del.SQL.Text := 'Delete from Arch_Artic WHERE id_Rec = :p_Num; ' +
                                      'Delete from Arch_Model WHERE Cod_Art = :p_Str; ' +
                                            (...)

ModDati.Qry_Del.Params.ParamByName('p_Num').AsInteger := Par_Num;
ModDati.Qry_Del.Params.ParamByName('p_Str').AsString := Par_Str;

che però mi dà errore all'inizio della seconda riga. Visto che in una istruzione SQL (senza parametri, però) questa sintassi multiriga è ammessa, in una query è una condizione normale oppure sbaglio qualcosa io?

Grazie anticipate.
Titolo: Re:Query di delete su più tabelle
Inserito da: xinyiman - Marzo 28, 2018, 08:21:51 am
Ciao, guarda dipende tutto da quale tipo di componenti usi. Ad esempio se usi le zeos lib non puoi usate le TZQuery in quel modo, ma devi usare il TZSQLProcessor per lavorare come vuoi tu.
Titolo: Re:Query di delete su più tabelle
Inserito da: Maxx - Marzo 28, 2018, 05:17:48 pm
Grazie Xiny, sempre molto gentile e puntuale.

Purtroppo nel labirinto delle librerie non mi muovo bene, vengo da ambienti del tutto diversi. Stavo tentando di usare l'SQLdb. Avevo cercato e trovato delle Stored Procedures fatte in modo molto simile e speravo potesse essere LA soluzione meno invasiva per il db.
Se sai, cortesemente, indicarmi un metodo altrettanto "leggero" altrimenti aprirò un po' di transazioni ad ogni ciclo.

Grazie.
Titolo: Re:Query di delete su più tabelle
Inserito da: nomorelogic - Marzo 28, 2018, 07:28:04 pm
se stai usando firebird probabilmente il modo migliore di passare più istruzioni in un colpo solo
è quello di fare uno script (puoi usare una TStringList ad esempio) che utilizzi la DML "EXECUTE BLOCK"
Titolo: Re:Query di delete su più tabelle
Inserito da: Stilgar - Marzo 29, 2018, 12:05:51 pm
Ciao.
Una soluzione CrossDatabase è lanciare le query una dopo l'altra. Senza ";" che sono caratteristici di uno script.
Al posto di aprire una transazione dentro al ciclo non puoi aprire una transazione prima di iniziare e committare alla fine il ciclo di elaborazione?
In questo modo hai una sola transazione attiva, per quanto diventi "cicciotta" alla fine del ciclo.
La soluzione ha il difetto che o tutto va bene in blocco o tutto va a farsi benedire.
Il vantaggio è di non aprire e chiudere continuamente transazioni.

Stilgar
Titolo: Re:Query di delete su più tabelle
Inserito da: Maxx - Marzo 29, 2018, 02:26:51 pm
Grazie, siete molto disponibili E mi mettete in imbarazzo.
Siete bravissimi MA mi mettete in imbarazzo.

Io ho tentato di capire le differenze tra le librerie e ciò che potevano, ciascuna, fare.
Purtroppo ho la necessità dell'impellenza e non molto tempo per risolvere. So, sono cosciente, che imparare a farsi la pappa è MOLTO meglio che trovare la pappa pronta e che apprendere a pescare sia molto meglio di un pesce avuto in dono, ma se poteste darmi un terreno un po' meno crudo su cui potermi muovere Ve ne sarei grato.
Non dico una query già bella pronta, ma sarebbe (e penso lo sarebbe per molti neofiti come me...) utile un tragitto del tipo: QUESTA libreria, in QUESTI casi, permette di fare QUESTE cose. QUELL'ALTRA libreria, etc.

Capisco di sfruttare studi e tempo che altri hanno fatto e speso. Ma il grosso problema che ho incontrato in Firebird e Lazarus è quello che spesso si incontra nell'affrontare un ambiente "Open Source" e Free: la proliferazione (di per sé eccellente) di direttive e comportamenti, che però porta ad una certa confusione per chi si avvicina da ambienti probabilmente meno "ricchi" di soluzioni ma con una sola distribuzione/metodo: meno possibilità ma anche meno variegature, ergo meno disordine nello studio e, nel mio specifico caso, nell'apprendimento.

Vi sarei grato, veramente, se le risposte fossero un tantino meno, alla luce delle mie conoscenze che non sono molte, criptiche.

Grazie di nuovo,
Maxx.
Titolo: Re:Query di delete su più tabelle
Inserito da: Maxx - Marzo 29, 2018, 02:44:31 pm
In questo modo hai una sola transazione attiva, per quanto diventi "cicciotta" alla fine del ciclo.
La soluzione ha il difetto che o tutto va bene in blocco o tutto va a farsi benedire.
Il vantaggio è di non aprire e chiudere continuamente transazioni.

Stilgar

Per quanto "cicciotta", la transazione non diverrebbe mai impossibile (i records trattati sono dell'ordine dei 2/3 mila ad ogni ciclo per 3 -  probabilmente 4 - tabelle); inoltre con possibilità d'errore estrinseco quasi nulla o addirittura nulla.
Puoi darmi più info su questo metodo e dove reperire istruzioni?
Ciò che ho trovato non è molto chiaro. Parla di allocazioni in diversi databases; io lavorerei in diverse tabelle ma nello stesso db.

Grazie Mr. Stilgar :)
Titolo: Re:Query di delete su più tabelle
Inserito da: Stilgar - Marzo 29, 2018, 03:41:49 pm
Ciao.
Molto semplicemente.
Apri la tranzazione.
Fai tutte le modifiche che ti servono
Committi.
Ora non ho capito quale connettore al db stai usando.
In genere usano nomi come startTransaction o simili.
Poi hanno commit/rollback.
Dovresti vedere il connettore come ti permette di controllare la transazione.
Le transazioni multi db in genere sono quelle a due fasi. Non ti servono quelle. 😉
Stilgar
Titolo: Re:Query di delete su più tabelle
Inserito da: Stilgar - Marzo 29, 2018, 04:17:05 pm
Sqldb mette a disposizione due oggetti che ti intetessano.
Uno di questi è documentato qui
https://www.freepascal.org/docs-html/fcl/sqldb/tsqltransaction.html
Titolo: Re:Query di delete su più tabelle
Inserito da: Maxx - Marzo 29, 2018, 04:52:41 pm
Gentilissimo.

Ora vediamo se ho capito:

- Apro il db (uso l'SQLdb di Lazarus, dipiùninzò...)
- Attivo la transazione
Ciclo while
  begin
  - Creo la query
  - Lancio la query
  - Creo altra query
  - Lancio altra query
  - Creo .... etc
  fine ciclo
commit alla transazione
chiudo la transazione
chiudo il db.

Fuochino???

Grazie,
Maxx
chiudo
Titolo: Re:Query di delete su più tabelle
Inserito da: Stilgar - Marzo 29, 2018, 04:54:26 pm
Esattamente quello che intendevo 😊
Titolo: Re:Query di delete su più tabelle
Inserito da: Maxx - Marzo 29, 2018, 04:56:46 pm
Ops,

Ciclo while
  begin
  - Creo la query
  - Lancio la query
  - Chiudo la query

  - Creo altra query
  - Lancio altra query
  - Chiudo altra query

  - Creo .... etc
  fine ciclo

Grazie infinite, Stilgar... Nemmeno fatto in tempo ad aggiungere una correzione al mio post.
Maxx
Titolo: Re:Query di delete su più tabelle
Inserito da: Stilgar - Marzo 29, 2018, 06:31:10 pm
Solo un suggerimento.
Al posto di creare e distruggere la query continuamente, recila l'istanza.
La crei/distruggi fuori dal ciclo.
All'interno del ciclo, modifichi le proprietà (query di aggiornamento e parametri) e la esegui.
Così eviti di perdere tempo nella costruzione e distruzione dell'istanza.
Titolo: Re:Query di delete su più tabelle
Inserito da: Maxx - Marzo 30, 2018, 01:21:26 pm
Ecco, qua mi suona già un pelo più ostico.
Sapevo (...o credevo!) che le query sono (siano) modificabili solo a transazione chiusa. Hai notizie diverse? A me dà errore.
Puoi indicarmi un esempietto sicuramente funzionante?

Grazie.
Titolo: Re:Query di delete su più tabelle
Inserito da: Stilgar - Marzo 30, 2018, 01:31:37 pm
Query.sql='select bla bla';
Query.exec;

Se ricordo bene, visto che non hai bisogno di leggere risultati, basta invocare l'esecuzione in questo modo.
Open e close aprono/chiudono il cursor in lettura. Per gli update/delete/insert è un "errore logico" usarli. Poi funziona lo stesso e pace. Ma attivi parti di codice inutile.
Usando il metodo corretto non crei e non distruggi la "query" ad ogni ciclo. Quindi guadagni anche qualche ciclo macchina. Cmq l'ide dovrebbe suggerirti il metodo con il nome corretto.

😊
Titolo: Re:Query di delete su più tabelle
Inserito da: Maxx - Aprile 01, 2018, 09:19:04 pm
Dear Mr. Stilgar,

Detesto essere pedante, ma sei sicuro che il metodo che mi hai suggerito sia praticabile?
Hai la possibilità di indicarmi quali istruzioni ed in che sequenza debbano essere eseguite? Da un paio di giorni sto dando fondo a tutte le combinazioni possibili ricevendo in risposta errori: dal non riconoscere un campo della tabella trattata nella query (che ovviamente c'è...) o, se lo trova, a darmi altri altri tipi di errore (impossibile su db aperto, impossibile su db chiuso, etc.).

Purtroppo conoscendo poco questo motore ed avendo pochissimo tempo per risolvere, chiedo un aiuto da seguire in pedissequo.
Più di offrire la mia riconoscenza ed una birra virtuale non posso fare.
E vi assicuro che chiedere aiuto è per me l'ultimissima opzione.

Grazie.
Titolo: Re:Query di delete su più tabelle
Inserito da: Stilgar - Aprile 02, 2018, 12:38:20 am
Vista la sequanza di errori db che menzioni ho solo la possibilità di aiutarti vedendo il codice.
Cosi in modo generico diventa difficilissimo azzeccare la causa (sarebbe solo fortuna da parte  mia, nom bravura ).
In gebere uso zeos db come connettore ai database. Mi permette di lavorare via codice come piace a me.
Cmq. Se lanci delle update/insert/delete non dovrebbe romperti l'anima....
Titolo: Re:Query di delete su più tabelle
Inserito da: Stilgar - Aprile 04, 2018, 09:10:10 pm
Perfetto 😊
Titolo: Re:Query di delete su più tabelle
Inserito da: Maxx - Aprile 04, 2018, 09:11:42 pm
Ciao Stilgar,

ci sono riuscito.

I problemi incontrati derivavano:

- dal fatto che quando cancelli un record, se esiste una chiave primaria devi informare Firebird che "metterai a Nil" questo campo e di non preoccuparsi ( --> Qry_Del.FieldByName('Cod_Art').Required := False;)

- dal fatto che ad ogni modifica del Qry_Del.SQL.TEXT facevo precedere questa riga dal Qry_Bigl.Edit mentre invece questo doveva essere sistemato prima del ciclo.

- facevo un Qry_Del.Post; ad ogni esecuzione della Query e per questo mi andava in errore.

Ho risolto con
 - istanziazione (dummy) della query prima del ciclo
 - apertura query
 - istruzione al db che i campi chiave saranno cancellati
 - edit della query.

e quindi la ciclazione con
 - modifica del SQL.TEXT
 - istruzione nuovo parametro
 - execute della query
per ogni tabella.

//--------------------------------------------------------------------------------------//

     i := 0;
     Qry_Del.SQL.Text := 'Select * from T_Articoli_AA WHERE Cod_Art = xxx';
     Qry_Del.Open;
     Qry_Del.FieldByName('id_Rec').Required := False;
     Qry_Del.FieldByName('Cod_Art_BB').Required := False;
     Qry_Del.FieldByName('Cod_Art_CC').Required := False;

     Qry_Del.Edit;

     while RecPointer <> nil do
       begin
          application.ProcessMessages;

          If (RecPointer^.flg_Big) then
          begin
                 Par_Num := (RecPointer^.id_Rec);
                  Par_Str := (RecPointer^.cod_Art);

                //Elimino i records da Articoli_AA
                Qry_Del.SQL.Text := 'Delete from T_Articoli_AA WHERE id_Rec = :p_Num';
                Qry_Del.Params.ParamByName('p_Num').AsInteger := Par_Num;
                Qry_Del.ExecSQL();

                //Elimino i records da Articoli_BB
                Qry_Del.SQL.Text := 'Delete from T_Articoli_BB WHERE Cod_Art_BB = :p_Str';
                Qry_Del.Params.ParamByName('p_Str').AsString := Par_Str;
                Qry_Del.ExecSQL();

                //Elimino i records da Articoli_CC
                Qry_Del.SQL.Text := 'Delete from T_Articoli_CC Where Cod_Art_CC = :p_Str';
                Qry_Del.Params.ParamByName('p_Str').AsString := Par_Str;
                Qry_Del.ExecSQL();

           end;

         RecPointer := RecPointer^.next;
         i := i + 1;
         ProgBar.Position := i;
       end;

       Qry_Del.Close;
       Transact.Commit;

Grazie infinite per avermi sopportato, per l'aiuto e per la tua/vostra grande disponibilità.
Siete veramente in gamba.
Titolo: Re:Query di delete su più tabelle
Inserito da: Maxx - Aprile 04, 2018, 09:13:08 pm
Ops.
Grazie.

Non so come mettere il risolto!!!
Ho fatto un mezzo casino :)
Titolo: Re:[Risolto] Query di delete su più tabelle
Inserito da: Stilgar - Aprile 04, 2018, 09:20:30 pm
Ci ho pensato io.
La prima è gratis.
Le prossime sono un calice di prosecco 😉