Newsgroup: it.comp.lang.visual-basic
Titolo: VB6 & MySQL: Aggiornamento recordset -> Errore

Ciao a tutti, seguo il newsgroup da un po' ma non sono mai intervenuto. 
Ho un problema. Sintetizzo il codice che riporto cosi da farla breve:
Una volta eseguito ritorna un errore nel quale si dice essere 
impossibile individuare la riga per l'aggiornamento.
Certo del fatto che questo errore sia uno dei più antichi di cui si sia 
discusso (non vedo elementi molto originali nel mio codice), qualcuno mi 
    indicherebbe gentilmente la causa o dove cercare qualche info?
Grazie a tutti
---------8<--------------8<---------------8<-----------CODICE
     Dim cnn As ADODB.Connection
     Set cnn = New ADODB.Connection
     Dim rst As ADODB.Recordset
     Set rst = New ADODB.Recordset
     cnn.CursorLocation = adUseClient
     cnn.Open strCnn
     rst.Open "messaggi", cnn, adOpenStatic, adLockOptimistic, adCmdTable
     rst.Filter = "idmessaggio=" & mID
     rst("evaso").Value = stato
     If IsNull(rst("dataora").Value) Then
         rst("dataora").Value = Format(Date, "yyyy-MM-dd") & " " & 
Format(Time, "hh:mm:ss")
     End If
     rst.Update
     rst.Close
     cnn.Close
     Set rst = Nothing
     Set cnn = Nothing



Hai semplicemente messo il carro davanti ai buoi e cioè hai fatto
l'aggiornamento del record senza testare se "hai" il record.
dovrebbe diventare qualche cosa di questo genere:
rst.open ....
if not rst.eof then
  rst.filter = xxxx
  if not rst.eof then
    rst.fields("evaso").value = xxx
  end if
end if
=======================================================================
Se mi vuoi scrivere togli le maiuscole
Sveltolampo 
cteniza...@hotmail.com
=======================================================================

Scusate, ma volendo non essere prolisso ho omesso dei particolari.
mID, che compare nell'istruzione filter, è l'id del record interessato, 
la cui esistenza è già stata verificata dal momento che la routine viene 
invoca dall'evento itemclick in un listview.
Mi ero già scontrato con questo errore ma avevo risolto cambiando 
tecnica. Ora vorrei capire. L'errore è documentato anche per SQL Server 
nell'utilizzo con ADO e la soluzione di MS sta nell'utilizzare corsori 
lato server per l'aggiornamento. Con MySQL non funziona.
Al limite basterebbe sapere che è un limite degli ADO. Ma riferito a 
cosa? Il problema non si presenta con tutti i tipi di dato, e spesso si 
presenta solo dopo che il field assume un valore (ovvero la prima voplta 
che si effettua il salvataggio tutto funziona).


 corsori lato server per l'aggiornamento. Con MySQL non funziona.
non so se la cosa si applica alla tua situazione, ma la butto lì lo stesso.
l'errore in oggetto può capitare se la tabella è priva di una chiave
primaria, o se tale chiave non è compresa nei campi raccolti dal recordset.
-- 
Salutoni
Sergio
per rispondere... togli il group dall'indirizzo

Si, mid è la chiave primaria e auto_increment. Come dici tu devono 
essere verificate le condizioni per cui sia possibile individuare 
univocamente il record interessato. In questo cosa credo lo siano, a 
meno che non mi sfugga qualcosa....
Ho provato anche a sostituire l'apertura della tabella da
rst.open "messaggi",[...], adcmdtable
a
rst.open "select * from messaggi[..],adcmdtext
ma il risultato è esattamente lo stesso.
Grazie


 meno che non mi sfugga qualcosa....
ricapitoliamo, per vedere se ho capito.
tu hai un recordset, sul quale riesci ad aggiungere record, ma non riesci a
modificare i record appena aggiunti, giusto?
la soluzione che mi viene in mente, in questo momento, è quella di eliminare
l'autoincremento sulla chiave primaria, in modo che possa essere tu a
imporgliene uno.
in effetti credo che quando tu fai un inserimento di un nuovo record, il
motore del db assegna l'id corretto, ma il lato client (il tuo recordset,
per intenderci) non riesce a sapere qual è, e quindi il successivo
aggiornamento di quel record fallisce perchè il motore non riesce ad
identificare qual è il record da aggiornare.
hth


Il problema nasce quando vado ad aggiornare i campi "evaso" e "dataora". 
Solo con essi si verifica l'errore. Se aggiorno altri campi dello stesso 
record tutto funziona. Ovvero
     rst.Open "messaggi", cnn, adOpenStatic, adLockOptimistic, adCmdTable
     rst.Filter = "idmessaggio=" & mID
     rst("evaso").Value = stato
     If IsNull(rst("dataora").Value) Then
         rst("dataora").Value = Format(Date, "yyyy-MM-dd") & " " & 
Format(Time, "hh:mm:ss")
     End If
     rst.Update <<<<<<<<<<-----------------ERRORE_
Se cambio _lo stesso codice_ in
     rst.Open "messaggi", cnn, adOpenStatic, adLockOptimistic, adCmdTable
     rst.Filter = "idmessaggio=" & mID
     rst("interno").Value = stato
     If IsNull(rst("account").Value) Then
         rst("dataora").Value = Format(Date, "yyyy-MM-dd") & " " & 
Format(Time, "hh:mm:ss")
     End If
     rst.Update <<<<<-----------------------TUTTO OK_
Ripeto, mi ero già imbattuto in questa stranezza, ma non era un periodo 
in cui avevo molto tempo ed ho risolto sostituendo il codice incriminato 
con una cnn.execute "UPDATE messaggi set[...] where idmessaggio=" & mID 
& ";"
Adesso però vorrei _capire_.
Intanto grazie


Davide Erbisti wrote:

Mi è capitato con Oracle.
Premetto che utilizzo i cursori lato client, ma mia soluzione è stata di 
salvare l'id (o gli id) in una variabile, eseguire il refresh del 
recordset e poi utilizzare un find (od un filter sfruttando un recordset 
clonato e poi assegnando il bookmark a quello originale).
altre soluzioni non ne avevo trovate.
Daniele

Adesso però vorrei _capire_.
Verifica la stringa di connessione:
http://dev.mysql.com/doc/connector/odbc/en/faq_3.html#Connection
in particolare quel "OPTION=3" il cui utilizzo è consigliato.
Che  connettore ODBC stai usando?
Vedi note del 3.51.06:
http://mirrors.ee.teiath.gr/mysql/Downloads/MyODBC3/RELEASE-NOTES
"-  Some times client side cursor type (adUseClient) generates
      error 'multi-step generated error' when performing result 
      set add, update or delete. But the same should work fine 
      when using server side cursor (adUseServer) from MyODBC 
      3.51.03 version."
Ciao!

 impossibile individuare la riga per l'aggiornamento.
Provato a mettere una colonna timestamp(14) sulla tabella?
Ciao, Sandro.
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

Grazie a tutti innanzi tutto.
Brutte notizie. Nessuna delle proposte ha sortito effetti diversi. Anche 
qui ho sostituito il codice originale con
cnn.execute "update....."
e tutto funziona regolarmente. Non so più che pensare.
Ciao


Di nuovo ciao a tutti.
Sentite questa. Se il campo dataora, di tipo "datetime" diventa di tipo 
"varchar(50)" tutto funziona, nessun errore... con il piccolo 
particolare che perdo la caratteristica del tipo (inaccettabile). Ho 
pensato potesse dipendere dal fatto che il format da VB ritorna comunque 
un formato ora che utilizza il punto come delimitatore (23.50.13) mentre 
MySQL usa i due punti (23:50:13). Provato a fare la sostituzione ma 
nulla da fare.
Idee? Io sono un po' a corto.
Ciao
Davide


Idee? Io sono un po' a corto.
Hai provato a passargli direttamente Now(), visto che il campo è un
datetime e non varchar/stringa?
... E il messaggio d'errore, non mi sembra d'averlo visto negli altri
post (numero e testo esatto)???
Ciao!

 nulla da fare.
Se il campo del DB è di tipo Datetime, il .Value del Field è anch'esso di
tipo Date, quindi il format non serve assolutamente.
Quando fai:
rst("dataora").Value = Format(Date, "yyyy-MM-dd") & " " &
Format(Time, "hh:mm:ss")
In realtà stai scrivendo:
 rst("dataora").Value = CDate(Format(Date, "yyyy-MM-dd") & " " &
Format(Time, "hh:mm:ss"))
Ma CDate è sensibile alla localizzazione, mentre il Format che utilizzi è
parzialmente delocalizzato.
Adesso, non ti so dire se il problema sia esattamente questo, ma sicuramente
ciò che fai non è corretto.
Oltretutto, faresti molto prima con un semplicissimo:
 rst("dataora").Value = Now()
Ciao
Alberto

Si, avete ragione. In effetti il codice originale, ovvero come era stato 
scritto all'inizio era
rst("dataora").value = Now()
ed è proprio in questo caso che si è proposto l'errore. Poi dopo n prove 
ne è venuto fuori quello che avete visto. Scusatemi.
L'errore comunque persiste e faccio fatica a capire.
Queste le righe originali
[...]
rst.Open "select * from messaggi where idmessaggio=" & mID & ";", cnn, 
adOpenForwardOnly, adLockOptimistic, adCmdText
     rst("evaso").Value = stato
     rst("dataora").Value = Now()
     rst.Update
[...]
Ma ve ne dico un'altra. L'errore si presenta solo la prima volta che il 
campo viene scritto, ovvero quando contiene il valore di default 
(0000-00-00 00:00:00).
Se forzo il codice in modo che il record venga scritto ogni volta che la 
scheda cui si riferisce viene aperta, tutto funziona. Peccato che tale 
sub debba essere richiamata proprio quando è la prima volta che viene 
aperta.
Che dire?


Questa l'apertura reale. Quella postata è uno stracico di altre prove 
che sto facendo.
rst.Open "select * from messaggi where idmessaggio=" & mID & ";", cnn, 
adOpenStatic, adLockReadOnly, adCmdText
Portate pazienza.
ciao
Davide


>> ciň che fai non č corretto.


Che dire?
Non che abbia capito molto di ciò che stai combinando, cmq ... forse
questo fa al caso tuo:
"-- ODBC can't support zero dates "0000-00-00". MyODBC automatically 
   converts 0000-00-00 dates to NULL.  Date columns that you want
   to update and that can be 0000-00-00 should not be declared as
   'NOT NULL'. "
Ciao!

 data fosse ritornata con i : anziché con il ., ma non cambia nulla.
Punti o due punti non cambia assolutamente nulla. Se lavori con i .Value
stai lavorando con valori privi di formato, quindi è un discorso che può
solo fuorviarti ed è meglio se lo abbandoni.
Piuttosto, nel tuo codice iniziale testi un Null, poi però parli di valore
di default "0000-00-00", quindi nel db non hai Null, ma un valore. Dal tuo
codice non so se tu usi ODBC o OleDb. Io con MySql ho sempre usato OleDb,
per cui non so se avvengono delle conversioni strane a livello di
transizione Odbc.
Curiosità: se invece di aprire il recordset con una select, lo apri puntando
all'intera tabella, e poi ti posizioni sul record con un filter, dà lo
stesso problema?
Una nota solo per 'correttezza stilistica': mID deve essere di tipo stringa,
altrimenti meglio mettere un CStr (ma non credo che sia legato al tuo
problema).
Ciao
Alberto

 Non che abbia capito molto di ciň che stai combinando, cmq ... forse


> Non che abbia capito molto di ciò che stai combinando, cmq ... forse


Ma come ti connetti al database?
Io ho provato una volta MyOLEDB e mi ci son trovato malissimo: le 
funzioni tipo COUNT(), SUM() e compagnia bella mi davano sempre ZERO. 
Non ho provato a manovrare le datetime... ma potrebbe darsi che i driver 
che usi per connetterti abbiano problemi.
Io uso MyODBC 3.51/3.52 e mi connetto con:
SConn = "Driver={MySQL ODBC 3.51 Driver; Server=localhost; 
Database=test; OPTION=3"
Connessione.Open SConn, Username, Password
e non ho mai avuto problemi di sorta.
Tu usi ODBC o altro?
-- 
Quando noi ignoranti eravamo di più,
tutto era più bello...
(Adriano Celentano)