Errore runtime 3197

di il
12 risposte

Errore runtime 3197

Nella procedura che segue, non riesco a venire a capo dell'errore 3197 (The Microsoft Office Access database engine stopped the process because you and another user are attempting to change the same data at the same time) sulla riga .update. Come si vede, la procedura modifica una data (in formato yyyymmdd) nel campo Testo e tenta di riscrivere il record modificato. Notare che essendo in test sono sicuramente l'unico user a lavorare su questo database, quindi non so a cosa imputare l'errore.


Sub modifyExpDate()


'Questa procedura modifica la data di scadenza del GP nei record della tabella Eventi di Hyperpower
'I dati trasferiti sono limitati ai record
'contenenti il codice GP e sono ordinati per numero evento

    
    Dim SQLStr As String
    Dim rs As DAO.Recordset
    Dim DataOld As String, DataNew As String, anno As String, mese As String, giorno As String
    
       
     SQLStr = "SELECT * FROM [HPEventi] WHERE Testo LIKE '%GP%' ORDER BY IDEvento"
'
    Set rs = CurrentDb.OpenRecordset(SQLStr, dbOpenDynaset, dbSeeChanges)
    
    'For each record in recordset we must isolate the date, format yyyymmdd, and add
    ' three months to it, then we write the record back
    
    With rs
        .MoveFirst
       Do While Not .EOF
         '   extract date
            DataOld = Mid(!testo, 10, 8)
            anno = Left(DataOld, 4)
            mese = Mid(DataOld, 5, 2)
            giorno = Right(DataOld, 2)
        ' incremento mese
            mese = mese + 3
        ' se mese > 12, incremento anno e prendo mese modulo 12
            If mese > 12 Then
                mese = mese Mod 12
                anno = anno + 1
            End If
        ' in ogni caso, formattiamo per leading zeroes
            mese = Format(mese, "00")
            giorno = Format(giorno, "00")
        ' ricostruiamo la data
            DataNew = anno & mese & giorno
        ' sostituiamo nel record
            .Edit
            !testo = Replace(!testo, DataOld, DataNew)
         
        .Update         '<==== qui c'è l'errore
        .MoveNext
       
        Loop
    End With
    
'            Tidy up
    rs.Close
    Set rs = Nothing
    Cn.Close
    Set Cn = Nothing
End Sub
Grazie per qualsiasi idea.

12 Risposte

  • Re: Errore runtime 3197

    Questa sintassi è sbagliata a prescindere, il JOLLY con DAO + [*] e non [%], a meno di usare SP ma non è il tuo caso:
    
    SQLStr = "SELECT * FROM [HPEventi] WHERE Testo LIKE '%GP%' ORDER BY IDEvento"


    Questa sintassi è giusta SOLO se usi un RDBMS come Server e non Access..., il dbSeeChanges se il Database sotto è Access non va bene:
    
    Set rs = CurrentDb.OpenRecordset(SQLStr, dbOpenDynaset, dbSeeChanges)
    Il Campo [Testo], parola che eviterei, di che tipo è...? Se è Data, il meccanismo non va bene, se fosse testo perchè lo devi modificare...? Il Formato di cui parli è ISO, quindi standard... non ne comprendo il senso, attenzione alla accezione anglosassone delle date nei Database....

    Puoi spiegarci come lavori...? e magari anche cosa devi fare nel concreto oltre che a dirci cosa hai fatto...!
  • Re: Errore runtime 3197

    Sono un po' confuso, ma provo a rispondere.
    La sintassi sarà sbagliata, ma seguendo il codice col debugger tutto fila liscio fino all'Update (poi sarà un caso, ma il primo record va bene, è sul secondo che si impianta).
    L'app è in vba access, ma le tabelle sono linked a quelle effettive nel database sotto SQLexpress, quindi nel RDBMS dovremmo esserci.
    Il campo Testo è un varchar, la data è parte della stringa (come del resto il codice GP che uso per estrarre solo i record che mi serve modificare); io la estraggo, la modifico e la sostituisco, come stringa. Dubito che il formato ISO qui c'entri molto: lavoro su una stringa di caratteri, non su una "data". La conversione a data gg/mm/aaaa viene fatta dopo, al di fuori di questa proc.
    Vorrei anche aggiungere che la seguente variante del codice, usando ADODB connection e ADODB recordset, funziona senza problemi (non occore neanche il .Edit prima della sostituzione). Evidentemente DAO recordset ha qualche requisito in più che mi sfugge. NB: la tabella in SQLEXPRESS si chiama Eventi, quella linked in access HPEventi
    
    Sub modifyExpDate()
    
    'Questa procedura modifica la data di scadenza del Green Pass nein record della tabella Eventi di Hyperpower i record dalla tabella Eventi di HyperPower
    'I dati trasferiti sono limitati ai record
    'contenenti il codice GP e sono ordinati per numero evento
    
        Dim Cn As ADODB.Connection
        Dim Server_Name As String
        Dim Database_Name As String
        Dim User_ID As String
        Dim Password As String
        Dim SQLStr As String
        Dim rs As ADODB.Recordset
        Dim DataOld As String, DataNew As String, anno As String, mese As String, giorno As String
        
        Set rs = New ADODB.Recordset
        
        
        Server_Name = "DESKTOP-FMBJ0FJ\SQLEXPRESS" ' Enter your server name here
    
        Database_Name = "RicevuteCPNCompletoBackup" ' Enter your database name here ATTENZIONE!!!
    
        User_ID = "sa" ' enter your user ID here
        Password = "xxxxx" ' Enter your password here
    
        SQLStr = "SELECT * FROM [Eventi] WHERE Testo LIKE '%GP%' ORDER BY IDEvento"
    '
    
       Set Cn = New ADODB.Connection
       Cn.Open "Driver={SQL Server Native Client 11.0};Server=" & Server_Name & ";Database=" & Database_Name & _
                ";Uid=" & User_ID & ";Pwd=" & Password & ";"
    
    
        rs.Open SQLStr, Cn, adOpenDynamic, adLockOptimistic
        
       
        'For each record in recordset we must isolate the date, format yyyymmdd, and add
        ' three months to it, then we write the record back
       ' Set rs = CurrentDb.OpenRecordset(SQLStr, dbOpenDynaset, dbSeeChanges)
        With rs
            .MoveFirst
           Do While Not .EOF
             '   extract date
                DataOld = Mid(!testo, 10, 8)
                anno = Left(DataOld, 4)
                mese = Mid(DataOld, 5, 2)
                giorno = Right(DataOld, 2)
            ' incremento mese
                mese = mese + 3
            ' se mese > 12, incremento anno e prendo mese modulo 12
                If mese > 12 Then
                    mese = mese Mod 12
                    anno = anno + 1
                End If
            ' in ogni caso, formattiamo per leading zeroes
                mese = Format(mese, "00")
                giorno = Format(giorno, "00")
            ' ricostruiamo la data
                DataNew = anno & mese & giorno
            ' sostituiamo nel record
            
                !testo = Replace(!testo, DataOld, DataNew)
             
            .Update
            .MoveNext
           
            Loop
        End With
        
    '            Tidy up
        rs.Close
        Set rs = Nothing
        Cn.Close
        Set Cn = Nothing
    End Sub
    
  • Re: Errore runtime 3197

    Scusa ma il codice di adesso è tutt'altra roba... usi ADO e non DAO quindi non ti stupire se ti vengono fatte osservazioni che ti sembrano poco coerenti... sai che differenza c'è tra i 2...? Mi pare sia da chiarire visto quello che ci hai proposto.

    Ora non basta buttare il codice nel forum, ma scrivere codice ed analisi serve anche a noi per capire che conoscenza hai tu in relazione alla richiesta.

    Io ho capito veramente poco di come operi... ed attendo chiarezza.
  • Re: Errore runtime 3197

    Se non lo avete ancora capito, sono un dilettante. Comunque:
    quello che sto cercando di fare mi sembra chiaro: la tabella eventi viene generata e riempita da un applicativo esterno alla mia giurisdizione. Si è scoperto che la data, infilata nel campo testo come stringa insieme ad altre info, era sbagliata di tre mesi. A causa del numero relativamente alto di record da correggere, si è pensato ad una procedura automatica: questa proc, quindi, è self contained.
    Ora, documentandomi qua e là su internet, ho trovato queste due soluzioni. Che differenza c'è fra DAO e ADODB? Non lo so esattamente. Quello che mi pare di capire è che se uso ADODB ho bisogno di accoppiarci il codice per ADODB connection: e quel codice funziona. Mi pare di capire che il codice usando DAO è più snello, ma non funziona come mi aspettavo. E' chiaro che potete dirmi: usa quello che funziona, e non rompere, ma mi sarebbe piaciuto capire se c'è differenza, se si possono usare entrambe le varianti o c'è qualcosa che lo impedisce, e poi perchè col DAO va tutto bene (il primo record viene aggiornato correttamente) fino al secondo record (errore 3197).
    Ho postato anche la variante che funziona; lo so anch'io che "il codice di adesso è tutt'altra roba", ma non capisco che vuol dire "capire come operi". Volevo solo capire perchè DAO dà quell'errore. Il fatto che SQLStr per DAO faccia riferimento alla tabella access (HPEventi linked alla tabella reale SQLEXPRESS)), mentre STRSql per ADODB faccia riferimento alla tabella reale (Eventi), può avere influenza? Se sono nel posto sbagliato, scusatemi.
  • Re: Errore runtime 3197

    Il fatto di non essere esperto è un problema, ma sicuramente non assolve dal cercare di evitare la confusione.
    Tu ne hai generata molta... oltre che a del codice nella sostanza inutile.
    Se operi con Tabelle LINKATE non hai bisogno di tutto quel papocchio..., anzi dal momento che il campo è già in formato ISO ti basta leggerlo convertitlo in Data ed usare DateAdd per sommare al campo uno span temporale definito, poi con Format lo riconverti.
    Basta una Query UPDATE con 1 riga di codice.
  • Re: Errore runtime 3197

    Sono decisamente nel posto sbagliato, e me ne scuso. Però contesto la confusione. Devo fare una cosa semplicissima: sostituire una (sotto)stringa con un'altra all'interno di un campo varchar di una tabella. Come dicevo, in questo momento l'ISO non mi interessa. Se dovessi sostituire "pippo" con "pluto" sarebbe esattamente la stessa cosa.
    Codice inutile? Può darsi, ma quale codice è inutile? Query update con 1 riga di codice? assumo una riga di codice per ogni record da cambiare, quindi dove sarebbe il problema ad usare il recordset per avere tutti i record da cambiare e agire su ognuno di essi in un loop?
    Per papocchio assumo tu intenda il codice elementare che uso di estrazione sottostringa, modifica componenti e ricostruzione, che tu proponi di fare con conversione a data, aggiunta dei tre mesi e riconversione a formato yyyymmdd. Ok, ma cosa cambia? alla fine devo comunque sostituire quella stringa alla precedente, quindi l'istruzione che conta è

    !testo = replace(!testo, dataold, datanew)
    come abbia ottenuto datanew prescinde dalla questione; non discuto dell'eleganza, ma il risultato è lo stesso

    Ma la domanda non riguarda questo: riguarda perchè l'update del record genera l'errore quando uso DAO.recordset. Ho già detto che è evidente che, usando DAO.recordset con riferimento alla tabella linkata, il codice è molto semplificato; peccato che non funzioni. Domanda banale: che cosa sbaglio?
    Comunque, sono nel posto sbagliato, me ne scuso, grazie a tutti.
  • Re: Errore runtime 3197

    roberto21 ha scritto:


    Sono decisamente nel posto sbagliato, e me ne scuso. Però contesto la confusione. Devo fare una cosa semplicissima: sostituire una (sotto)stringa con un'altra all'interno di un campo varchar di una tabella. Come dicevo, in questo momento l'ISO non mi interessa. Se dovessi sostituire "pippo" con "pluto" sarebbe esattamente la stessa cosa.
    Codice inutile? Può darsi, ma quale codice è inutile? Query update con 1 riga di codice? assumo una riga di codice per ogni record da cambiare, quindi dove sarebbe il problema ad usare il recordset per avere tutti i record da cambiare e agire su ognuno di essi in un loop?
    Questo è il problema del non avere minimamente una conoscenza...
    1 Query eseguita, modifica tutti i Records afferenti al Criterio eventuale, nessun LOOP serve.

    roberto21 ha scritto:


    Per papocchio assumo tu intenda il codice elementare che uso di estrazione sottostringa, modifica componenti e ricostruzione, che tu proponi di fare con conversione a data, aggiunta dei tre mesi e riconversione a formato yyyymmdd. Ok, ma cosa cambia? alla fine devo comunque sostituire quella stringa alla precedente, quindi l'istruzione che conta è

    !testo = replace(!testo, dataold, datanew)
    come abbia ottenuto datanew prescinde dalla questione; non discuto dell'eleganza, ma il risultato è lo stesso
    No, ti ho già spiegato che una Query fa tutto, non voglio convincerti ed il fatto tu non lo capisca... anzi lo metta in discussione non capendolo... problema non mio.

    roberto21 ha scritto:


    Ma la domanda non riguarda questo: riguarda perchè l'update del record genera l'errore quando uso DAO.recordset. Ho già detto che è evidente che, usando DAO.recordset con riferimento alla tabella linkata, il codice è molto semplificato; peccato che non funzioni. Domanda banale: che cosa sbaglio?
    La domanda è banale quando si sa di cosa si parla... non è il tuo caso.
    Ci sono MOLTE cause che giustificano la NON funzionalità, alcune te le ho dette, e non le hai capite... pazienza.

    roberto21 ha scritto:


    Comunque, sono nel posto sbagliato, me ne scuso, grazie a tutti.
    Si credo non sia il posto giusto.
  • Re: Errore runtime 3197

    Ciao,
    se cerchi su google "ms acces error 3197 linked table sqlserver"
    dovresti trovare altri che hanno avuto il tuo stesso problema con DAO.

    Forse usando DAO con la linked table, se invece di scrivere select *
    scrivi
    select 'solo i campi della PK e quello che devi aggiornare' eviti i campi della linked table fastidiosi.

    Con ADODB vai direttamente su sqlserver e non passando per le linked table access
    non incorri nel problema dei campi fastidiosi di sqlserver che access rimappa sui suoi.

    P.S.
    personalmente per risolvere il tuo problema, avendo un pò di conoscenza di T-SQL e SQL in generale e visto che la data sembrainiziare sempre alla stessa posizione,
    non avrei neanche messo in mezzo access ma avrei fatto un'unica UPDATE direttamente in sql server sfruttando
    le sue funzioni SUBSTRING, e CONVERT
    ( prendi il pezzo prima della data , la data in formato YYYYMMDD la trasformi in data con convert aggiungendo 3 mesi
    e la riconverti in stringa sempre con convert; aggiungi il pezzo dopo la data
    )


    HTH
  • Re: Errore runtime 3197

    Grazie a sspintux per il suggerimento costruttivo. E naturalmente grazie ad Alex per la pazienza dimostrata. Ho solo un dubbio: premesso che sono un dilettante, pensavo (evidentemente a torto) di imparare, anche sbagliando, cominciando dalle tecniche, diciamo così, più semplici e che conoscevo. Siccome la scienza purtroppo non viene infusa, pensavo che pian piano magari arrivavo alla soluzione e imparavo qualcosa di più sofisticato. Ho chiesto lumi a qualche esperto, ma non ho avuto risposte, solo critiche alla mia ignoranza. Pazienza, prendo atto, sopravviverò e continuerò a cercare di imparare.

    La domanda è banale quando si sa di cosa si parla... non è il tuo caso.
    Ci sono MOLTE cause che giustificano la NON funzionalità, alcune te le ho dette, e non le hai capite... pazienza.


    OK, non so di che cosa parlo... ma magari Alex mi saprebbe indicare dove mi ha citato alcune cause della NON funzionalità. Io non le ho trovate, ma magari erano volutamente camuffate per dimostrare la mia ignoranza... tentativo perfettamente riuscito. Per quanto riguarda la query update, ci sto studiando, ma ancora non ci sono arrivato, l'ignoranza è una brutta cosa.
    Grazie a tutti. Argomento chiuso.
  • Re: Errore runtime 3197

    Scusate, riapro un attimo. Soluzione trovata, per chi fosse interessato.
    La tabella Eventi contiene un campo Data, tipo Datetime. Modificando il tipo di questo campo a SmallDateTime, l'errore sparisce. Come ignorante, non è che capisca molto il perchè, evidentemente la gestione di quel tipo è diversa.
    Grazie ad un altro forum, in cui ho trovato questo suggerimento.
  • Re: Errore runtime 3197

    roberto21 ha scritto:


    Come ignorante, non è che capisca molto il perchè
    ....
    .... veramente ti avevo dato una risposta nel forum sqlserver ... oltre che su questo sul perchè.

    Cmq, importante è che hai risolto.

    P.S.
    Se quel campo data-ora non fa parte della PK e lo togli dalla select che usi con DAO
    ( come ti avevo suggerito qui) forse ti funziona lo stesso senza modificare
    il tipo di campo in sqlserver
  • Re: Errore runtime 3197

    Assolutamente d'accordo. Avevo dimenticato l'entri sotto sql server dopo che avevo spostato la domanda sotto access, visto che lì era sbagliato. Avevi perfettamente individuato lka causa (o una delle cause), ma l'altro forum mi ha anche suggerito la soluzione ;: a cambiare datetime in smalldatetime non ci sarei arrivato.
    Grazie ancora.
Devi accedere o registrarti per scrivere nel forum
12 risposte