2009-03-12 2 views
6

[Edit 2: Weitere Informationen und das Debuggen in Antwort unten ...]Problem Daten in MS Access-Datenbank einfügen mit ADO über Python

Ich bin ein Python-Skript zu schreiben MS Access-Datenbanken in eine Reihe von Text zu exportieren Dateien, um eine aussagekräftigere Versionskontrolle zu ermöglichen (Ich weiß - warum Access? Warum verwende ich keine bestehenden Lösungen? Sagen wir einfach, die Einschränkungen sind nicht technischer Natur).

Ich habe erfolgreich den vollständigen Inhalt und die Struktur der Datenbank mit ADO und ADOX über die Comtypes-Bibliothek exportiert, aber ich bekomme ein Problem, die Daten erneut zu importieren.

ich den Export der Inhalt jeder Tabelle in eine Textdatei mit einer Liste in jeder Zeile, etwa so:

[-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'] 

Und die folgende Funktion, die die Datei zu importieren:

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() 

Alles funktioniert einwandfrei, außer dass numerische Werte (double und int) als Nullen eingefügt werden. Irgendwelche Ideen, ob das Problem mit meinem Code, eval, comtypes oder ADO ist?

Edit: Ich habe das Problem mit dem Einfügen von Zahlen behoben - Casting sie als Strings (!) Scheint das Problem für beide Doppel-und Integer-Felder zu lösen.

Allerdings habe ich jetzt ein anderes Problem, das zuvor durch das Obige verdeckt wurde: das erste Feld in jeder Zeile wird auf 0 gesetzt, unabhängig vom Datentyp ... Irgendwelche Ideen?

Antwort

4

Und eine Antwort gefunden.

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

Muss sein:

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

Jetzt nur schauen müssen in ich, warum. Hoffe nur, diese Frage rettet jemand anderen ein paar Stunden ...

+0

Und der Rest der Lösung bestand darin, "rs.Fields [i] .Value = data [i]" in "rs.Fields [i] .Value = str (data [i])" zu ändern? – BIBD

+0

Nein, nein. Sollte explizit gesagt haben: das Hinzufügen der dynamischen = True löste sowohl das ursprüngliche Problem mit numerischen Werten als auch das Folgeproblem mit variablen Ergebnissen. Sobald es an Ort und Stelle war, funktionierte rs.Fields [i] .Value = data [i] gut und tatsächlich warf das Umwandeln der Zahlen als Strings einen Typ-Mismatch-Fehler. – mavnn

+0

Kewl, ich war nicht klar auf die Antwort. An dieser Stelle würde ich sagen, markieren Sie Ihre eigene Antwort als Akzeptiert. – BIBD

0

Wird data[i] als String behandelt? Was passiert, wenn Sie es beim Aufruf von rs.Fields[i].Value als int/double deklarieren?

Was passiert auch, wenn Sie den Inhalt von rs.Fields[i].Value ausdrucken, nachdem er eingestellt wurde?

+0

Siehe bearbeiten - bizarrely ich musste speziell von int/double in string umwandeln, um es zur Arbeit zu bringen ... – mavnn

0

Keine vollständige Antwort, aber es scheint ein Problem während des Updates zu sein. Ich habe einige weitere Debugging-Code in dem Einführungsprozess hinzugefügt, die die folgenden (Beispiel einer einzelnen Zeile aktualisiert wird) erzeugt:

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] 

Der letzte Wert in jedem „Eingesetzte ...“ Linie ist das Ergebnis des Aufrufs rs.Fields [i] .Wert vor dem Aufruf von rs.Update(). Die Zeile "After ..." zeigt die Ergebnisse des Aufrufs von rs.Fields [i] .Value nach dem Aufruf von rs.Update().

Noch ärgerlicher ist, dass es nicht zuverlässig versagt. Erneutes Ausführen der exakt gleichen Code auf dem gleichen zeichnet ein paar Minuten später generiert:

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] 

Wie Sie sehen können, die Ergebnisse zuverlässig sind, bis Sie sie begehen, dann ... nicht.

Verwandte Themen