2009-03-12 7 views
6

[Edit 2: Maggiori informazioni e il debug in risposta qui sotto ...]Problema L'inserimento dei dati nel database di MS Access utilizzando ADO tramite Python

Sto scrivendo uno script python per esportare MS Access database in una serie di testi file per consentire un controllo più significativo della versione (lo so - perché Access? Perché non utilizzo le soluzioni esistenti? Diciamo solo che le restrizioni non sono di natura tecnica).

Ho esportato con successo l'intero contenuto e la struttura del database utilizzando ADO e ADOX tramite la libreria comtypes, ma sto riscontrando un problema nel reimportare i dati.

sto esportare il contenuto di ogni tabella in un file di testo con un elenco su ogni linea, in questo modo:

[-9, u'No reply'] 
[1, u'My home is as clean and comfortable as I want'] 
[2, u'My home could be more clean or comfortable than it is'] 
[3, u'My home is not at all clean or comfortable'] 

E la seguente funzione per importare il file di detto:

import os 
import sys 
import datetime 
import comtypes.client as client 
from ADOconsts import * 
from access_consts import * 

class Db: 
    def create_table_contents(self, verbosity = 0): 
     conn = client.CreateObject("ADODB.Connection") 
     rs = client.CreateObject("ADODB.Recordset") 
     conn.ConnectionString = self.new_con_string 
     conn.Open() 
     for fname in os.listdir(self.file_path): 
      if fname.startswith("Table_"): 
       tname = fname[6:-4] 
       if verbosity > 0: 
        print "Filling table %s." % tname 
       conn.Execute("DELETE * FROM [%s];" % tname) 
       rs.Open("SELECT * FROM [%s];" % tname, conn, 
         adOpenDynamic, adLockOptimistic) 
       f = open(self.file_path + os.path.sep + fname, "r") 
       data = f.readline() 
       print repr(data) 
       while data != '': 
        data = eval(data.strip()) 
        print data[0] 
        print rs.Fields.Count 
        rs.AddNew() 
        for i in range(rs.Fields.Count): 
         if verbosity > 1: 
          print "Into field %s (type %s) insert value %s." % (
           rs.Fields[i].Name, str(rs.Fields[i].Type), 
           data[i]) 
         rs.Fields[i].Value = data[i] 
        data = f.readline() 
        print repr(data) 
        rs.Update() 
       rs.Close() 
     conn.Close() 

Tutto funziona bene eccetto che i valori numerici (double e int) vengono inseriti come zeri. Qualche idea su se il problema è con il mio codice, eval, comtypes o ADO?

Modifica: Ho risolto il problema con l'inserimento di numeri: il loro cast come stringhe (!) Sembra risolvere il problema sia per i campi double sia per quelli interi.

Tuttavia, ora ho un problema diverso che era stato precedentemente oscurato da quanto sopra: il primo campo in ogni riga è impostato su 0 indipendentemente dal tipo di dati ... Qualche idea?

risposta

4

E ha trovato una risposta.

rs = client.CreateObject("ADODB.Recordset") 

deve essere:

rs = client.CreateObject("ADODB.Recordset", dynamic=True) 

Ora ho solo bisogno di esaminare il motivo. Spero solo che questa domanda salvi qualcun altro qualche ora ...

+0

E il resto della soluzione era di cambiare "rs.Fields [i] .Value = data [i]" in "rs.Fields [i] .Value = str (data [i])"? – BIBD

+0

No, no. Dovrebbe aver detto esplicitamente: aggiungendo il dinamico = Vero risolto sia il problema originale con valori numerici, sia il problema di follow-up con risultati variabili. Una volta installato, rs.Fields [i] .Value = data [i] ha funzionato correttamente e in effetti il ​​cast dei numeri come stringhe ha generato un errore di mancata corrispondenza del tipo. – mavnn

+0

Kewl, non ho avuto la risposta chiara. A questo punto direi di contrassegnare la tua risposta come accettata. – BIBD

0

È il data[i] trattato come una stringa? Cosa succede se lo si specifica espressamente come int/double quando si imposta rs.Fields[i].Value?

Inoltre, cosa succede quando si stampa il contenuto di rs.Fields[i].Value dopo averlo impostato?

+0

Vedi modifica - bizarramente ho avuto bisogno di espressamente castare da int/double a string per farlo funzionare ... – mavnn

0

Non ancora una risposta completa, ma sembra essere un problema durante l'aggiornamento. Ho aggiunto qualche ulteriore codice di debug nel processo di inserimento che genera il seguente (esempio di una singola fila essendo aggiornato):

Inserted into field ID (type 3) insert value 1, field value now 1. 
Inserted into field TextField (type 202) insert value u'Blah', field value now Blah. 
Inserted into field Numbers (type 5) insert value 55.0, field value now 55.0. 
After update: [0, u'Blah', 55.0] 

L'ultimo valore in ogni "inserito ..." linea è il risultato della chiamata rs.Fields [i] .Value prima di chiamare rs.Update(). La riga "Dopo ..." mostra i risultati della chiamata a rs.Fields [i] .Valore dopo aver chiamato rs.Update().

Ciò che è ancora più fastidioso è che non sta fallendo in modo affidabile. Eseguire nuovamente lo stesso codice esattamente sulla stessa registra qualche minuto dopo generati:

Inserted into field ID (type 3) insert value 1, field value now 1. 
Inserted into field TextField (type 202) insert value u'Blah', field value now Blah. 
Inserted into field Numbers (type 5) insert value 55.0, field value now 55.0. 
After update: [1, u'Blah', 2.0] 

Come si può vedere, i risultati sono affidabili fino a commetterli, allora ... no.

Problemi correlati