Istruzione delete che a volte "non cancella"

di il
7 risposte

Istruzione delete che a volte "non cancella"

Buongiorno a tutti,

ho un problema su una tabella di un DB SQL Server, sulla quale memorizzo Targhe di camion,  per la chiamata al carico tramite un maxi display di un parcheggio.

Una volta chiamata, questa targa la devo eliminare (e di regola funziona….diciamo al 90%, il che significa che a volte, questa targa continuo a trovarla in tabella).

Ho messo dei log che vanno a scrivere su un file txt tutti i passaggi, e nel file vedo che l'istruzione delete è stata fatta.

Ora, l'unico dubbio che a questo punto mi viene è questo.

Ho un timer che ciclicamente controlla il contenuto della tabella, per impacchettare i dati e inviarli al display.

Potrebbe essere plausibile che se l'istruzione Delete avviene proprio nell'attico in cui il timer esegue la query, questa possa essere bloccata ?

Al momento non ho altre idee:(

Grazie a tutti

Saluti

D.

7 Risposte

  • Re: Istruzione delete che a volte "non cancella"

    06/12/2022 - DanieleG ha scritto:


    Potrebbe essere plausibile che se l'istruzione Delete avviene proprio nell'attico in cui il timer esegue la query, questa possa essere bloccata ?

    Ma per la DELETE stai usando una transazione, vero?

  • Re: Istruzione delete che a volte "non cancella"

    @DanieleG, inziamo con gli assiomi ;-)

    ASSIOMA: SQL Server (che e' un prodotto alla pari di Oracle) non si perde pezzi per strada ;-)

    Essendo questo un assioma, vuol dire che il problema NON E' SQL Server ma il suo utilizzo.

    Ora QUANDO puo' capitare che una DELETE non funzioni? 
    In paio di casi: 

    1. quando viene fatto il ROLLBACK della transazione in cui la DELETE e' stata eseguita
    2. quando la DELETE viene fatta in una transazione, alla quale non viene MAI fatto il COMMIT (il che vuol dire che prima o poi viene fatto il ROLLBACK) 
      E
      la SELECT che usi per estrarre i dati viene eseguita in un'ALTRA TRANSAZIONE la quale, ovviamete, per le PROPRIETA' delle transazioni e delle regole di funzionamento, NON VEDE il fatto che e' stata fatta la DELETE (ed e' assolutamente giusto cosi')

    Ma questi NON SONO malfunzionamenti della DELETE OPPURE delle transazioni, ma un errato uso delle transazioni stesse.

    Ora, supponendo il punto 2 MA in cui fai il COMMIT, e' possible, ma ALTAMENTE IMPROBABILE (per i tempi di esecuzione che sono nell'ordine dei millisecondi o anche meno) che SE la SELECT viene fatta un'epsilon prima della DELETE, la SELECT intercetta la targa un'attimo prima che venga cancellata.
    Ma COMUNQUE, SE la DELETE va a buon fine, la targa viene SICURAMENTE, al 100%, eliminata dalla tabella.

    Quindi, bisogna andare a spulciare il codice per capire dove sta' la “”castronata"".

  • Re: Istruzione delete che a volte "non cancella"

    Aggiungo anche eventuale dead lock e riferimento in tabella secondaria.

  • Re: Istruzione delete che a volte "non cancella"

    Buongiorno e grazie a tutti per le risposte.

    Tanto per essere chiari, ed evitare assiomi, non ho mai detto (o pensato) che il problema fosse SQL Server, in quanto è abbastanza noto anche ai più sprovveduti che è un DBMS con le contro-palline (per rimanere in tema Natalizio)

    Io parto sempre dal presupposto che la castroneria è lato sviluppatore (nello specifico mia).

    riporto il pezzo di codice dove cancello la targa:

            If Open_Connection("SELECT * FROM Tab_Pannello WHERE Targa = '" & sTarga & "'") = True Then
               With rsPiazzola  ----? (recordset inizializzato nella Open_Connection)
                   If .RecordCount Then
                       .Delete
                       eventLog  "TERMINALE PESA - Eliminazione Targa da Pannello: " & sTarga
                   End If
               End With
               chiudiConnessione 8
           End If

    NB: In testa a tutto c'è il controllo dell'errore, che verrebbe riportato su un apposito file, invece, viene puntualmente inserito il log  “TERMINALE PESA - Eliminazione Targa da Pannello….”, ma  (ripeto solo in alcuni sporadici casi), questa continua a essere presente in tabella.

    Grazie

    Buona giornata a tutti 

    D.

  • Re: Istruzione delete che a volte "non cancella"

    In caso di fallimento del comando delete, successivamente riesci a eliminare il record?

    Potresti provare (finchè non ne vieni a capo) a tracciare meglio cosa succede.

    Prima dell'azione di cancellazione, fai il log di :
    - query di selezione eseguita
    - records estratti (intendo proprio le righe di dati, quanto meno le colonne indice / chiavi)

    dopo il comando di eliminazione, da capo:
    - riesegui la query di selezione e la inserisci nel log
    - records estratti (intendo proprio le righe di dati)
    - verifichi se è ancora presente il record e in questo caso inserisci ulteriore riga nel log in modo da ricercare facilmente l'azioen di cancellazione che non ha funzionato

    Se fattibile in base al contesto della tua applicazione:
    Usa il profiler di SQL server e crei la traccia con i filtri del caso per fare il log delle query e loro riscontro

  • Re: Istruzione delete che a volte "non cancella"

    La riposta è si

    per tenere traccia (a prescindere da questo problema) di quanto inviato al pannello nel parcheggio, avevo implementato una piccola form dove visualizzo le righe presenti in quella tabella, con la possibilità di selezionarli ed eliminarli.

    Per cui nei casi di mancata eliminazione (ovvero il cliente vede chiamare delle targhe che in realtà non sono più presenti in stabilimento), entra in quella form e le elimina senza problemi.

    Ora per puro scrupolo, farò una modifica in cui terrò in memoria le targhe da eliminare, e le eliminerò subito dopo l'evento scatenato dal timer che esegue la query.

    grazie

    Ciao

    D.

  • Re: Istruzione delete che a volte "non cancella"

    07/12/2022 - DanieleG ha scritto:


    riporto il pezzo di codice dove cancello la targa:

            If Open_Connection("SELECT * FROM Tab_Pannello WHERE Targa = '" & sTarga & "'") = True Then
               With rsPiazzola  ----? (recordset inizializzato nella Open_Connection)
                   If .RecordCount Then
                       .Delete
                       eventLog  "TERMINALE PESA - Eliminazione Targa da Pannello: " & sTarga
                   End If
               End With
               chiudiConnessione 8
           End If

    Io onestamente non gestirei la cancellazione in questo modo, ossia sfruttando il cursore del record acquisito in fase di lettura e verificando il numero di record, che tra l'altro non è una informazione che viene sempre restituita (a volte basta un SET NOCOUNT ON per bloccarla).

    Dovresti predisporre dei metodi per le operazioni CRUD sul tuo database che siano indipendenti tra loro, ovvero scrivere una procedura che - data una targa in ingresso - recuperi tutti i dati relativi tramite la SELECT, magari verificando anche quanti sono i record caricati (non ho capito se la targa è anche una chiave univoca o se ci possono tendenzialmente essere più targhe con stesso valore nella tabella).

    In secondo luogo, non cablerei il valore all'interno dello statement SQL usando la concatenazione di stringhe, ma farei sempre e solo uso dei parametri, una tematica spesso incontrata su questo forum e caldamente suggerita per evitare effetti collaterali facilmente aggirabili, oltre a SQL Injection e altre vulnerabilità.

    Alla funzione che individua la targa tramite SELECT ne affiancherei un'altra che effettua la cancellazione usando lo statement SQL appropriato, ossia scrivendo una query del tipo “DELETE FROM Tab_Pannello WHERE Targa = @Targa” da lanciare quando è necessario eliminare questa targa dal database.

    Ad ogni operazione su DB, deve corrispondere una procedura/funzione che faccia le seguenti cose:

    • apertura di una nuova connessione al DB SQL Server,
    • valorizzazione dei parametri richiesti (es. targa),
    • esecuzione dello statement SQL (es. INSERT, SELECT, DELETE, UPDATE),
    • trasferimento di eventuali risultati e valori di ritorno, se richiesti,
    • chiusura della connessione (forzata, ovvero garantita in qualsiasi contesto, anche in caso di errore).

    Prova a rivedere la tua implementazione con questi suggerimenti e aggiornaci sull'esito.

    Ciao! :)

Devi accedere o registrarti per scrivere nel forum
7 risposte