Topic: [RISOLTO]: Problema ASSURDO con PyODBC  (Letto 72 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline es_plata

  • python unicellularis
  • *
  • Post: 5
  • Punti reputazione: 0
    • Mostra profilo
[RISOLTO]: Problema ASSURDO con PyODBC
« il: Giugno 20, 2019, 12:57 »
Buon giorno,
sono anni che sono iscritto e, credo, che questo sia il primo post.
Sempre trovo le soluzioni ai miei problemi nelle risposte e nei vari trheads. Pero questo non ce la faccio.
Sono un programmatore della domenica per hobby...

Spiego il problema (assurdo).
Possiedo una DataBase Access (credo 2000 è un .mdb), mi trovo sotto Windows 10 Pro, con Python (3.6.4 64Bit) .
le import che ho usato (alternativamente) sono:
  • import pyodbc
  • import odbc
evidentemente nella seconda opzione ho creato il DNS (64Bit) in windows, e mi sono accertato che funzioni.

Ció che neccesito é modificare tutta una serie di records...
in una variabile definisco la sentenza SQL:

SentenzaSQL ='SELECT * FROM Tabella WHERE (Anno = 2018, Dipartimento=10)  ORDER BY Dataoperazione ASC'
cursore.execute(SQL)
variabileTemporanea= cursore.fetchall()
for i in variabileTemporanea:
   Logid = i[0]
   campoa = i[2]
   compoaToccato = campoa + 'ci voglio ficcare questo testo'
   NuovaSQL = 'UPDATE Tabella  SET campoa="' + campoaToccato + '" WHERE Logid = '+str(Logid)
  cursor.execute(NuovaSQL)

Mi direte... "bravo, sei un genio dei database"... ed io rispondo "grazie ,non credo prorpio"..
Il ciclo inizia a "girare", poi ricevo il messaggio:
«
Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    a.execute(SQL)
dbi.integrityError: [Microsoft][Controlador ODBC Microsoft Access] Los cambios solicitados en la tabla no se realizaron correctamente porque crearían valores duplicados en el índice, clave principal o relación. Cambie los datos en el campo o los campos que contienen datos duplicados, quite el índice o vuelva a definirlo para permitir entradas duplicadas e inténtelo de nuevo. in EXEC
»
Come é mai possibile che abbia un indice duplicato!!! non sto facendo una "INSERT"... é una stupidissima "UPDATE"..
Per favore, sono due settimane che mi ci friggo la testa...

Se l'errore mi sorgesse all'inizio del ciclo, sarebbe evidente che la falla sta li.. peró si presenta in maniera casuale...mi corregge 1500 records e poi si presenta...

Ringrazio anticipatamente per i suggerimenti che possiate inviare.

« Ultima modifica: Giugno 26, 2019, 12:44 da es_plata »

Offline nuzzopippo

  • python unicellularis
  • *
  • Post: 40
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema ASSURDO con PyODBC
« Risposta #1 il: Giugno 20, 2019, 13:25 »
Ciao, da quel che esponi, in effetti il Tuo problema è strano, anche quando utilizzavo access e VB (20 anni fa) non mi è mai capitato un errore di indice in un update.

Come è strutturata la Tavola? A quali relazioni è soggetta? Logid è un valore univoco oppure no?
Domande giusto per avere una idea di base.

Poi, hai provato ad inserire la procedura di aggiornamento dei dati in un blocco "try -> except" e farti stampare la query che ti da errore (e magari anche la precedente) per poterla valutare?

[Edit] ... e pensandoci un po' su :
Il testo da inserire è costante? Se la risposta è "SI", hai provato ad utilizzare la discriminante per l'estrazione dei dati per l'update, invece dello Logid?, in sostanza una query di questo tipo :

   testo_da_aggiungere = 'quello che vuoi'
   NuovaSQL = 'UPDATE Tabella  SET campoa= CONCAT(campoa, "' + testo_da_aggiungere + '") WHERE (Anno = 2018, Dipartimento=10)'
  cursor.execute(NuovaSQL)

... anche se, a dire il vero, non ricordo proprio se Access implementi "CONCAT()" ... da una ricerca fatta ora, dovrebbe essere :
   NuovaSQL = 'UPDATE Tabella  SET campoa=  "' + testo_da_aggiungere + '" + campoa WHERE (Anno = 2018, Dipartimento=10)'
« Ultima modifica: Giugno 20, 2019, 14:04 da nuzzopippo »

Offline es_plata

  • python unicellularis
  • *
  • Post: 5
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema ASSURDO con PyODBC
« Risposta #2 il: Giugno 20, 2019, 15:10 »
La tabella NON ha relazioni...
Ho provato ed ottengo lo stesso errore...Un giorno ho voluto essere "cattivo" ed ho eseguito le operazioni "manualmente" nella IDE creandomi una matrice con le sentenze SQL e cancellandole mano a mano che si eseguivano...
Notai che gli errori, in quel caso, si presentavano dopo 88, 44, 22, 11, 1...(...)
Il problema NON é di estrazione... ciucciare i dati me li ciuccia... é il "update"... l'l'unico riferimento univoco é il campo Logid...
Per quanto concerne il "concat"... precisamente per evitare questo tipo di problemi, preferisco PRIMA crearmi una sentenza unica poi la eseguo... se fai caso non uso la notazione %s%s ...

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.862
  • Punti reputazione: 9
    • Mostra profilo
Re:Problema ASSURDO con PyODBC
« Risposta #3 il: Giugno 21, 2019, 09:55 »
Mah guarda, il codice che hai postato fa riferimento a un contesto che non conosciamo, oltre a essere un intrico di Cose Da Non Fare e Cose Incomprensibili, secondo tutti i manuali... ma anche lasciando perdere i problemi specifici, la cosa che devi prima di tutto capire è che il tuo assunto di base

> Come é mai possibile che abbia un indice duplicato!!! non sto facendo una "INSERT"... é una stupidissima "UPDATE".

è sbagliato.
E' anzi possibilissimo e molto frequente avere un indice duplicato facendo una UPDATE... se aggiorni un record in un campo indicizzato e per caso lo setti a un valore già presente in qualche altro record, ovviamente avrai un errore di indice duplicato, proprio come se facessi una INSERT. Non c'è niente da stupirsi per questo.

La mia impressione, da una lettura al volo del tuo codice (che peraltro è parecchio confuso) è che tu stia facendo un errore concettuale. Tu forse stai pensando questo: "prendo le righe della tabella a una a una, e aggiorno quel campo indicizzato semplicemente aggiungedo una stringa fissa al valore che già c'è. Che male c'è? Se i valori non erano duplicati prima, non è certo possibile che diventino duplicati adesso, aggiungendo una stringa fissa a ciascun valore del campo..."
L'errore è che NON stai prendendo TUTTE le righe della tabella, visto che la query di SELECT da cui peschi i dati ha un bel WHERE. Quindi probabilmete quello che succede è che a un certo punto capita che un valore aggiornato diventi uguale a un altro *che non avevi pescato* ma che comunque esiste già nella tabella...

Esempio per capire meglio. Metti che hai una tabella fatta così:

ID   col1   col2(indice!)
=========================
1    pera   "giallo verde"
2    pera   "nero blu"
3    pera   "bianco blu"
4    mela   "nero"
5    mela   "giallo"

Poi immagina di fare una query del tipo select * from table where col1="mela", e poi immagina di aggiornare i recordi che peschi (che sono il 4 e il 5) aggiungedo "verde" al testo di col2 (indicizzata). Adesso vedi bene che la tabella dovrebbe diventare

ID   col1   col2(indice!)
=========================
1    pera   "giallo verde"
2    pera   "nero blu"
3    pera   "bianco blu"
4    mela   "nero verde"
5    mela   "giallo verde"  -> OOOOOPSSSSSS!!!! indice duplicato!!!

Ed ecco svelato come una "stupidissima UPDATE" può causare un indice duplicato. Non c'è niente di magico, è davvero solo sql di base. Ed è anche un problema frequentissimo, si capisce: aggiornare un campo indicizzato può portare a errori di indici duplicati. Vedi un po'... è proprio quello a cui servono gli indici unique sui campi...

Poi a dire il vero c'è anche il caso un pochino più esotico in cui ANCHE se peschi TUTTI i record della tabella potresti trovarti comunque con un errore di indice duplicato. Basta che *in qualsiasi momento* un indice sia duplicato, e tutto si ferma anche se per te "alla fine" l'operazione dovrebbe comunque riuscire, da un punto di vista logico. Per esempio, se fosse

ID   col1   col2(indice!)
=========================
1    pera   "giallo"
2    pera   "nero"
3    pera   "bianco"
4    mela   "giallo verde"

e tu volessi aggiungere a ciascuna riga la stringa "verde", vedi bene che già al momento di aggiornare il record 1 avresti un duplicato con il 4... anche se alla fine il 4 dovrebbe poi diventare "giallo verde verde" e quindi non sarà duplicato, il problema è che *in quel momento* hai l'errore e tutto si ferma... Questo è più fastidioso perché ovviamente l'errore dipende dall'ordine in cui sono fatte le modifiche... Può darsi che la cosa migliore in questi casi sia cancellare momentaneamente l'indice, fare l'update e poi ripristinare l'indice... ma dipende dagli internals del database...

Offline es_plata

  • python unicellularis
  • *
  • Post: 5
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema ASSURDO con PyODBC
« Risposta #4 il: Giugno 21, 2019, 12:17 »
Desidero ringraziare RicPol per il tempo che ha dedicato,  aggiungendo che é un gusto leggerlo sempre, poiché é sempre molto preciso (oltre che critico) nelle sua affermazioni.

Circa il codice non dico niente ho premesso la mia NON professionalitá.
Circa l'osservazione presentata lo verifico, sebbene il campo indice trattasi precisamente del famoso Logid... gli altri non dovrebero esere indicizzati..
la tabella pressappoco é una cosa standard:
Logid!dataora!idpersona!
1!2018/05/31 10:00:03!4!
4!2018/05/31 11:00:03!5!
5!2018/06/01 09:00:03!4!
Quando vado ad aggiornare dico:
UPDATE Tabella SET idpersona = 99 WHERE Logid = 4

Tutto dovrebbe funzionare se, come dici correttamente , idpersona, in realtá non sia un indice...

Verifico e poi racconto.

Offline es_plata

  • python unicellularis
  • *
  • Post: 5
  • Punti reputazione: 0
    • Mostra profilo
Re:RISOLTO: Problema ASSURDO con PyODBC
« Risposta #5 il: Giugno 26, 2019, 12:44 »
Vorrei ringraziare RicPol, grazie al quale, sono riuscito a risolvere.
Ho effettuato le seguenti verifiche:
  • prima di tutto ho pensato che potesse dipendere da un "eccesso" di dati inviati al driver ODBC di Access, il quale non essendo stato pensato per grandi volumi di dati e per un uso, sostanzialmente manuale, non riuscisse a digerirli.
    Ho introdotto una  "sleep(2)"... Non ha sortito effetto
  • Successivamente sono andato a controllare la struttura del database, evidentemente uno dei campi  - esattamente quello che io andavo ad aggiornare (SET campo = nuovovalore) impediva i valori duplicati - sebbene non indicizzato
Saludos.