Esecuzione di doppia query simultanea

di il
14 risposte

Esecuzione di doppia query simultanea

Buongiono a tutti,

situazione attuale: eseguo la copia di dati ottenuti da palmare da una tabella temporanea  SQL (import) e li trasferisco ad una definitiva (movimenti) dello stesso DB e fin qui tutto tranquillo. Questo il codice:

 Try
           con.ConnectionString = constring
           con.Open()
           cmd.Connection = con
           cmd.CommandText = "insert into movimenti (mv_listino, mv_conto, mv_datae, mv_datau, mv_datac, mv_codart, mv_qta, mv_mese, mv_anno, mv_marcatura, mv_prezzo, mv_descr, mv_peso, mv_nota, mv_costo) " &
               " select im_liscosto, im_conto, im_datae, im_datau, im_datae, im_codart, im_qta, im_mese, im_anno, im_marcatura, im_prezzo, im_descr, im_peso, im_nota, im_costo from import "
           cmd.ExecuteNonQuery()
   Catch ex As Exception
           MessageBox.Show("Errore di inserimento in SQL Server. " & ex.Message)
           Exit Sub
   Finally
           con.Close() 'Chiude la connessione.
   End Try

Dopo l'esecuzione di cui sopra si svuota la tabella import. 

Ora però avrei la necessità di intervenire durante la copia tra una tabella e l'altra e, se il record ha un certo valore nel campo ‘im_marcatura’ dovrei aggiornare una terza tabella.

Come posso inserire la seconda query di update?

Pensavo di fare due cicli separati prima di svuotare la tabella import ma se si interrompesse la connessione tra la prima e la seconda query avrei le tabelle disallineate.

Grazie per ogni suggerimento in merito

14 Risposte

  • Re: Esecuzione di doppia query simultanea

    28/03/2024 - Dummy ha scritto:


    ma se si interrompesse la connessione tra la prima e la seconda query avrei le tabelle disallineate.

    in che senso? 

    prendi i dati (source) li carichi su una tabella import (target), verifichi che nr.record tabella source sia uguale a tabella target  ed in locale aggiorni le tabelle (o lo fai fare ad un trigger che provvede magari anche a svuotare la tabella target).

    se il record ha un certo valore nel campo ‘im_marcatura’ dovrei aggiornare una terza tabella…

    quindi le due tabelle non conterranno gli stessi record.

  • Re: Esecuzione di doppia query simultanea

    28/03/2024 - Dummy ha scritto:


    se il record ha un certo valore nel campo ‘im_marcatura’ dovrei aggiornare una terza tabella.

    Se questa condizione è vera per qualsiasi inserimento nella tabella [Movimenti], non dovresti agire lato client ma lato DB. Imposti un trigger DML AFTER.

    Altrimenti nel caso in cui l'inserimento di record lo fai da un'altra parte ti devi ricordare ogni volta che devi richiamare le due operazioni e non solo una. Potenzialmente una rogna bella grossa.

  • Re: Esecuzione di doppia query simultanea

    @SIhandrea infatti le tabelle non contengono gli stessi dati, la terza tabella viene aggiornata con dati statistici relativi a nazione/zona

    @Sgrubak  Grazie mille, non avevo pensato ai trigger (troppo concentrato sul codice) A volte la risposta è semplice

    Grazie a entrambi

  • Re: Esecuzione di doppia query simultanea

    28/03/2024 - Sgrubak ha scritto:


    Se questa condizione è vera per qualsiasi inserimento nella tabella [Movimenti], non dovresti agire lato client ma lato DB. Imposti un trigger DML AFTER.

    Per quanto i trigger possono costituire uno strumento valido in alcune circostanze, occorre sempre tenere presente che questa operazione può creare potenzialmente dei problemi, ad esempio in caso di importazioni o nell'esecuzione di operazioni massive di inserimento e/o di update.

    28/03/2024 - Sgrubak ha scritto:


    Altrimenti nel caso in cui l'inserimento di record lo fai da un'altra parte ti devi ricordare ogni volta che devi richiamare le due operazioni e non solo una. Potenzialmente una rogna bella grossa.

    Per evitare questa rogna, il rischio è poi quella di avere un trigger da accendere e spegnere alla bisogna quando si devono fare operazioni di manutenzione sui dati della tabella.

    28/03/2024 - Dummy ha scritto:


    infatti le tabelle non contengono gli stessi dati, la terza tabella viene aggiornata con dati statistici relativi a nazione/zona

    Se l'obiettivo è quello di aggiornare dati statistici, quindi tendenzialmente dati che a pieno regime tenderanno a variare di poco, al netto della questione del trigger, a mio avviso non è corretto farlo contestualmente all'inserimento e/o modifica di dati, perché all'aumentare della quantità di informazioni, le operazioni di inserimento e aggiornamento verranno sempre più rallentate da azioni correlate e concomitanti che vanno ad aggiornare basi di dati che potrebbero invece essere alimentate in un secondo momento, con frequenza minore, facendo una estrazione separata dei dati stessi. Vedi ad esempio come funziona un “dataware house”.

    In conclusione, valuta bene come stai procedendo perché “agganciare” operazioni di aggiornamento di dati calcolati e tendenzialmente storici oppure “offline” nello stesso momento in cui si vanno ad aggiungere e/o modificare dati recenti e “live”, non è praticamente mai una buona idea: meglio evitare la doppia query e limitarsi alla prima, lasciando a una procedura esterna il compito di andare a recuperare i dati periodicamente e aggiornare le informazioni statistiche.

  • Re: Esecuzione di doppia query simultanea

    29/03/2024 - Alka ha scritto:


    può creare potenzialmente dei problemi, ad esempio in caso di importazioni o nell'esecuzione di operazioni massive di inserimento e/o di update

    Vero ma le operazioni massive o manutentive le vedo più come un qualcosa di sporadico/eccezionale. Nel caso, avrò sicuramente molte precauzioni da prendere e disabilitare eventuali trigger credo venga naturale.

    A mio sentimento, se devo fare una INSERT mi devo limitare a quello e basta. Deve essere poi compito del DB sapere cosa succede dopo. Non dovrebbe essere lui stesso a sapere come mantenera la sua integrità?

    29/03/2024 - Alka ha scritto:


    Se l'obiettivo è quello di aggiornare dati statistici, quindi tendenzialmente dati che a pieno regime tenderanno a variare di poco, al netto della questione del trigger, a mio avviso non è corretto farlo contestualmente all'inserimento e/o modifica di dati

    Su questo mi ci ritrovo. Il punto sostanziale è che solitamente avere dei campi calcolati (direttamente od indirettamente) è una cosa poco sensata. Credo si vada ad aumentare inutilmente la dimensione del DB salvando dati che possono comunque essere calcolati da una query.

    Potrebbe comunque starci nel caso in cui queste elaborazioni siano particolarmente “pesanti” computazionalmente e siano richieste di frequente. In quel caso potrebbe avere senso aggiornarli di volta in volta durante gli inserimenti.

  • Re: Esecuzione di doppia query simultanea

    29/03/2024 - Sgrubak ha scritto:


    Vero ma le operazioni massive o manutentive le vedo più come un qualcosa di sporadico/eccezionale. Nel caso, avrò sicuramente molte precauzioni da prendere e disabilitare eventuali trigger credo venga naturale.

    Una operazione massiva può essere banalmente quella di dover inserire e/o aggiornare un numero di record in modalità batch o per “row set” invece che “row by row”. Non mi riferisco esclusivamente a un intervento di manutenzione sporadico.

    I trigger risultano estremamente limitativi da questo punto di vista e sono spesso un “collo di bottiglia”, analogamente all'uso di cursori, poiché costituiscono codice SQL che viene eseguito “a fronte di qualcosa” e non per richiesta esplicita del comando SQL che si invia al database (non fa parte dell'istruzione); in breve è un “side effect” che in alcuni contesti può generare situazioni difficili da tenere sotto controllo, come il prolungarsi della durata di una transazione, il rischio di deadlock quando ve ne sono più di uno che eseguono in ordine differente a seconda del contesto, e tante altre situazioni che qualunque DBA esperto può descriverti nella propria esperienza.

    29/03/2024 - Sgrubak ha scritto:


    A mio sentimento, se devo fare una INSERT mi devo limitare a quello e basta. Deve essere poi compito del DB sapere cosa succede dopo. Non dovrebbe essere lui stesso a sapere come mantenera la sua integrità?

    Se devi fare una INSERT, fai una INSERT. Se le regole di business dettano che le INSERT devono essere due, il tuo codice ne deve fare due: suddividerle una nel codice C#/VB.NET e l'altra in SQL Server non ha alcuna utilità ai fini pratici, mentre rende il tutto prono a molti rischi, fermo restando che anche un eventuale “passaggio di consegne” o documentazione del progetto deve tenere conto dell'esistenza di queste due entità disgiunte ma strettamente correlate fra di loro per ricostruire il quadro completo delle operazioni che avvengono all'interno del DB.

    In linea generale, un trigger è utile per scopi di audit, logging semplificato, integrazione con database esistenti per travasare dati (pochi) all'interno di altre strutture applicative che devono relazionarsi con software legacy, ma con tutte le metodologie che abbiamo a disposizione oggi (tra SOLID, TDD, ecc.), le architetture (microservizi, ecc.), i linguaggi, i framework e così via, anche se non si deve realizzare un sistema così complesso, partire creandosi scientemente un possibile problema in futuro è inaccettabile. Dal mio punto di vista, ovviamente. :)

    29/03/2024 - Sgrubak ha scritto:


    Credo si vada ad aumentare inutilmente la dimensione del DB salvando dati che possono comunque essere calcolati da una query.

    No, l'utilità del fare un calcolo non la si misura dal fatto che un certo dato può essere sempre determinato da una query, ma da quanto velocemente si vuole arrivare a reperire quel dato: se molti utenti desiderano avere in tempi brevi (leggi istantaneamente) una certa informazione, o se l'inclusione di altre tabelle in join rende complessa (leggi lenta) la query da eseguire, in molti di questi casi il costo di ridondare il dato è di gran lunga infinitamente inferiore a quello di eseguire la query inutilmente più estesa del dovuto.

    Lavorare con i database è sempre un “trade off”, ma non c'è nulla che sia del tutto inutile o utile in senso assoluto.

    Lo stesso vale per i trigger, intendiamoci, e infatti il mio suggerimento di NON utilizzarli tiene conto dello scenario: non capisco come sia più rapido aggiornare una tabella correlata a un dato modificato via SQL con un trigger rispetto all'aggiungere l'esecuzione di una ulteriore UPDATE all'interno del codice, ma a parte questo giudizio di merito - come dicevo sopra - non vedo di buon occhio lo “split” di due operazioni da fare in termini di business suddividendole a priori tra codice e trigger SQL, in due posti diversi, con due linguaggi diversi, che assolvono alla persistenza nello storage (il database di SQL Server) una unica informazione.

    29/03/2024 - Sgrubak ha scritto:


    Potrebbe comunque starci nel caso in cui queste elaborazioni siano particolarmente “pesanti” computazionalmente e siano richieste di frequente. In quel caso potrebbe avere senso aggiornarli di volta in volta durante gli inserimenti.

    Come dicevo, se l'aggiornamento è richiesto ai fini statistici, allora si elimina l'UPDATE in loco, si elimina il trigger e si delega tutto a una procedura che estrae i dati e, dalla fotografia, aggiorna di conseguenza la tabella statistica.

    La mia era comunque una ipotesi: sarà l'autore della discussione (se vuole) a dirci qualcosa di più. :)

  • Re: Esecuzione di doppia query simultanea

    29/03/2024 - Alka ha scritto:


    anche se non si deve realizzare un sistema così complesso, partire creandosi scientemente un possibile problema in futuro è inaccettabile. Dal mio punto di vista, ovviamente. :)

    È quello il trick: avere esperienza a sufficienza.

    Grazie per aver condiviso il tuo punto di vista. Un po' ti odio perché ho trovato altri argomenti che vorrei studiare (TDD e relativa XP che non conoscevo). XD Vedrò di mettere nel carrello qualche nuovo testo…

    29/03/2024 - Alka ha scritto:


    Come dicevo, se l'aggiornamento è richiesto ai fini statistici, allora si elimina l'UPDATE in loco, si elimina il trigger e si delega tutto a una procedura che estrae i dati e, dalla fotografia, aggiorna di conseguenza la tabella statistica.

    Mi metto a studiare e provo a vedere se ne vengo a capo. Era proprio convinto che un trigger fosse la strada buona.

    Grazie di nuovo!

  • Re: Esecuzione di doppia query simultanea

    Un bel dibattito…

    Ha chiesto come fare per aggiornare due tabelle da una connessione ad un db esterno (presumo) ponendosi il problema di una interruzione fortuita di connessione.

    Nello specifico se dopo aver aggiornato tabellaA perde qualcosa mentre aggiorna tabellaB (nella quale vanno inseriti solo alcuni dati della tabella importata).

    Lo scenario sembra quello di una catena di supermercati dove ci si collega per estrapolare il venduto e tra questi il venduto del cedi (centro distribuzione) che magari confliisce su altra tabella che riceve anche il venduto di altri affiliati, quindi in loco non si possono fare statistiche di tutta la catena degli affiliati e quindi per fini statistici si intende altra tabella contenitore.

    In quest'ottica, il suggerimento è stato: 

    1. Importi i dati su una tabella provvisoria tabellaimportvenduto.
    2. Confronto nr record tabella fonte con nr record tabellaimportavenduto (anche con filtro per idcentro).
    3. Se coincidono non ci sono stati errori di trasmissione ne interruzioni di connessione.
    4. Creare un trigger  attivabile al'eliminazione dei record (il trigger interviene prima del comando).
    5. Il trigger prende i record filtrati per centro e li inserisce nella tabella vendite.
    6. Se nel dato abbiamo la condizione per la quale il dato va anche nella tabellaB inserisce anche il rcord nella tabellaB.
    7. Finito il trigger vengono eliminati i record di quel centrocosti dalla tabella temporanea.
    8. Questo per tutti gli affiliati (presumibilmente la sera quando si fanno le chiusure).
    9. Alla fine resta una tabella vuota e sempre vuota deve restare.

    Se il trigger si attiva al comando delete ma che cosa e che senso ha disabilitare un trigger che non si attiva in quanto la tabella è vuota?

    Non ha neanche senso manutenere una tabella vuota.

    Anche in caso di manutenzione, si blocca il sistema all'utente quindi la tabella non attiva alcun trigger.

    Ma, in tutto questo, chi deve dire la sua è l'autore del questito.

  • Re: Esecuzione di doppia query simultanea

    28/03/2024 - Dummy ha scritto:


    Come posso inserire la seconda query di update?

    Pensavo di fare due cicli separati prima di svuotare la tabella import ma se si interrompesse la connessione tra la prima e la seconda query avrei le tabelle disallineate.

    Ciao,

    Che la tabella sia una o due o tre o enne da aggiornare , nulla cambia… sia per la prima o per la seconda o per le enne query, si può verificare una disconnessione a sql server per qualsiasi motivo….

    Quindi avrai comunque un problema sia per la prima tabella che per l'ultima che deve essere aggiornata.

    Per ovviare a tali problemi di solito:….

    • si usa una Using trans As SqlTransaction = con.BeginTransaction()
    • all'interno della transazione si inseriscono tutte le query da eseguire
    • al termine di tutte le cmd.ExecuteNonQuery() si esegue il commit delle transazioni
    • il tutto si mette in un try e nella
      • Catch ex As Exception 
        si intercetta il messaggio di errore MessageBox.Show(ex.Message) 
        e a questo punto si esegue il rollback della transazione 
    • in caso di errore o di sconnessione e/o altro, nessuna modifica viene apportata alle tabelle
    • si legge il messaggio e si rolve il problema che ha causato l'errore di eccezione 
    • quando è stato risolto il problema che ha causato l'errore e/o gli errori, si esegue nuovamente l'import

    In questo modo si evitano modifiche parziali ai dati di una o di tutte le tabelle coinvolte nel processo di import.

    Esempio:

    Try
        Using con As New SqlConnection(constring)
            con.Open()
            Using trans As SqlTransaction = con.BeginTransaction()
                Using cmd As New SqlCommand()
                    cmd.Connection = con
                    cmd.Transaction = trans
    
                    ' prima query 
                    cmd.CommandText = "...."
                    cmd.ExecuteNonQuery()
    
                    ' seconda query
                    cmd.CommandText = "...."
                    cmd.ExecuteNonQuery()
                    
                    ' terza query
                    ' ecc.ecc.ecc......
    
                End Using
                ' commit
                trans.Commit()
            End Using
        End Using
    Catch ex As Exception
        MessageBox.Show("Error : " & ex.Message)
        ' rollback della transazione e non rimuovere i dati da importare in attesa di sisolvere il problema occorso 
    End Try

    Risolto l'errore e/o gli errori, allora riesegui l'import dall'inizio. Nulla va perso e tutto viene scritto nelle tabelle solo se non emergono errori di eccezione. Se invece ci sono errori, nulla viene scritto nelle tabelle e ritorna tutto come era in origine.  …e rifai l'import ;-))

    Ciaoooo ;-)

  • Re: Esecuzione di doppia query simultanea

    29/03/2024 - Sgrubak ha scritto:


    Mi metto a studiare e provo a vedere se ne vengo a capo. Era proprio convinto che un trigger fosse la strada buona.

    Può essere una strada, ma non capisco come sia più facile - mentre stai scrivendo codice che esegue una query di inserimento/aggiornamento - metterne una di seguito piuttosto che andare a scrivere la stessa cosa con un altro linguaggio (TSQL) in un altro sistema, legandolo all'operazione iniziale.

    Hai fatto un INSERT/UPDATE? E allora fanne un'altra, magari in transazione, o se i dati secondari non sono così importanti da essere aggiornati in “real time”, fallo separatamente con un altro servizio o applicazione dedicata che alimenti quella parte. :)

    29/03/2024 - sihsandrea ha scritto:


    Ha chiesto come fare per aggiornare due tabelle da una connessione ad un db esterno (presumo) ponendosi il problema di una interruzione fortuita di connessione.

    Se il database è lo stesso, o almeno si tratta dello stesso server, allora non ci sono problemi da porsi: vale quanto detto sopra, banalmente mettendo tutto in transazione, così come ha descritto By65Franco.

    Se i due server sono totalmente distinti, a maggior ragione non si utilizza un trigger, che potrebbe risultare estremamente lento nell'esecuzione se invocato in fase di modifica dei dati del primo database a causa delle tempistiche di aggiornamento del secondo: si aggiorna solo il database locale e si configura - tramite replica o applicativo custom - l'alimentazione “eventuale” (in differita) del sistema esterno.

  • Re: Esecuzione di doppia query simultanea

    30/03/2024 - Alka ha scritto:


    Se il database è lo stesso, o almeno si tratta dello stesso server, allora non ci sono problemi da porsi:

    Buongiorno Alka…

    purtroppo e capita spesso, da parte dell'OP quasi mai viene fornita un analisi esaustiva dello scenario in cui opera. 
    Spesso nell'esposizione manca sempre qualche dettaglio che può fare la differenza tra una soluzione ed un altra, tra un approccio ed un altro.

    Ma i concetti in linea generali sono comunque quelli enunciati… sta all'OP capire come strutturare questo flusso di lavoro avendo a disposizioni enne possibili soluzioni con approcci diversi atti e adatti allo scopo.


    Ritengo che non sia un problema di tecnica, di come scrivere e con quali metodi, un flusso di codice che aggiorna il database.
    Quando si aggiorna un databse si adottano sempre e comunque gli stessi accorgimenti atti a mantenere integre le informazioni che verranno manipolate.

    Voglio dire che esistono modalità assolutamente standard da applicare ogni qualvolta si aggiornano i dati nelle tebelle del database.

    Adesso le ipotesi sono sul tavolo, vediamo l'OP cosa intende fare …. 

    Auguri buone feste

    ciaooo ;-)

  • Re: Esecuzione di doppia query simultanea

    Scusate l'assenza ma ho avuto dei problemi in questi giorni.

    Ho letto l'interessante discussione che si è aperta sull'uso dei trigger e credo di dover dei chiarimenti ulteriori.

    La situazione è effettivamente quella di una GDO con molte righe di movimento ma in una situazione ‘terzista’. I movimenti vengono passati anonimizzati e devono servire a creare una situazione vendite mensilizzata. Contestualmente c'è una tabella annuale che viene alimentata per alcune statistiche di zona commerciale.

    La prima tabella (movimenti) viene raggruppata ed esportata ogni mese con le statistiche merceologiche (anonime per zona e/o marca) dopodichè viene svuotata (ecco perchè non è più possibile poi generare le statistiche per zona commerciale che invece hanno vita e svuotamento annuale)

    Da questi 2 postulati nasce la questione doppia query o trigger. Leggendo la discussione credo che opterò per una soluzione da codice con l'eventuale ‘rollback’ come suggerito da By65Franco.

    Ringrazio proprio tutti per l'attenzione, il tempo e la ricchezza della discussione, mi sento proprio come diceva il grande Battiato: “Non voglio sentirmi intelligente guardando dei cretini, preferisco sentirmi cretino guardando persone intelligenti” 

    Grazie a tutti

  • Re: Esecuzione di doppia query simultanea

    Salve,

    personalmente valuto sempre molto attentamente l'implementazione di trigger AFTER UPDATE per l'insieme di controindicazioni indicate anche da @Alka… la scrittura di un valido trigger multirows spesso puo' diventare cosa non banale…

    in questi casi preferisco solitamente permettere le operazioni DML tramite solo apposite stored procedures, dove la (relativa) flessibilita' del linguaggio SQL utilizzato permette molta piu' flessibilita' e duttilita'. 

    [flame]
    In maniera molto db centric, per tutto il primo decennio e parte del secondo decennio di questo secolo non permettevo affatto accesso “diretto” alle base table e tutto avveniva esclusivamente tramite stored procedures che potevamo controllare/verifcare esplicitamente… poi gli ORM ci hanno (purtroppo??? :D ) tolto quest'arma… 
    [/flame]

    my €0.02

    salutoni romagnoli
    – 
    Andrea

  • Re: Esecuzione di doppia query simultanea

    30/03/2024 - asql ha scritto:


    in questi casi preferisco solitamente permettere le operazioni DML tramite solo apposite stored procedures, dove la (relativa) flessibilita' del linguaggio SQL utilizzato permette molta piu' flessibilita' e duttilita'. 

    Questa alternativa effettivamente non l'avevo contemplata, ma a tutti gli effetti è senz'altro molto più sicura ed efficace della soluzione con il trigger: quantomeno tutte le operazioni sono in un unico punto, la stored procedure, e c'è un controllo preciso delle operazioni eseguite e soprattutto della transazione.

    30/03/2024 - asql ha scritto:


    In maniera molto db centric, per tutto il primo decennio e parte del secondo decennio di questo secolo non permettevo affatto accesso “diretto” alle base table e tutto avveniva esclusivamente tramite stored procedures che potevamo controllare/verifcare esplicitamente… poi gli ORM ci hanno (purtroppo??? :D ) tolto quest'arma… 

    Io lavoro ancora per un cliente in cui questa è una realtà, e devo dire - da sviluppatore - che può avere un suo senso. :)

Devi accedere o registrarti per scrivere nel forum
14 risposte