2009-03-12 15 views
6

[Edit 2: Więcej informacji i debugowanie w odpowiedzi poniżej ...]Problem Wkładanie danych do bazy danych MS Access przy użyciu ADO za pośrednictwem Python

Piszę skrypt Pythona do eksportu bazy danych MS Access do serii tekstu pliki, aby umożliwić bardziej znaczącą kontrolę wersji (wiem - dlaczego Access? Dlaczego nie używam istniejących rozwiązań? Powiedzmy, że ograniczenia nie mają charakteru technicznego).

Udało mi się wyeksportować pełną zawartość i strukturę bazy danych przy użyciu ADO i ADOX przez bibliotekę komtaków, ale pojawia się problem z ponownym importem danych.

ja eksportuje zawartość każdej tabeli do pliku tekstowego z listą na każdej linii, tak jak poniżej:

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

I Poniższa funkcja importowania wspomniany plik:

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

Wszystko działa poprawnie, z wyjątkiem tego, że wartości liczbowe (podwójne i wewnętrzne) są wstawiane jako zera. Jakieś pomysły dotyczące tego, czy problem dotyczy mojego kodu, ewaluacji, typów komend lub ADO?

Edycja: Naprawiono problem z wstawianiem liczb - rzucanie ich jako ciągi (!) Wydaje się rozwiązywać problem zarówno dla pól podwójnych, jak i całkowitych.

Mam jednak inny problem, który wcześniej był zasłonięty przez powyższe: pierwsze pole w każdym wierszu jest ustawione na 0 niezależnie od typu danych ... Jakieś pomysły?

Odpowiedz

4

I znalazłem odpowiedź.

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

musi być:

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

Teraz wystarczy spojrzeć na dlaczego. Mam tylko nadzieję, że to pytanie uratuje kogoś innego przez kilka godzin ...

+0

A pozostałą częścią rozwiązania była zmiana "rs.Fields [i] .Value = data [i]" na "rs.Fields [i] .Value = str (data [i])"? – BIBD

+0

Nie, nie. Powinienem powiedzieć jednoznacznie: dodanie dynamicznego = prawda rozwiązało zarówno pierwotny problem z wartościami liczbowymi, jak i problem kontynuacji ze zmiennymi wynikami. Gdy już było na miejscu, rs.Fields [i] .Value = data [i] działało poprawnie i w rzeczywistości rzucanie liczb jako ciągów powodowało błąd typu niedopasowanie. – mavnn

+0

Kewl, nie miałem jasności co do odpowiedzi. W tym momencie chciałbym zaznaczyć własną odpowiedź jako zaakceptowaną. – BIBD

0

Czy data[i] jest traktowany jako ciąg? Co się stanie, jeśli rzucisz go jako int/double, gdy ustawisz rs.Fields[i].Value?

Co się stanie, gdy wydrukujesz zawartość rs.Fields[i].Value po jej ustawieniu?

+0

Zobacz redagować - dziwacznie musiałem specjalnie rzucić od int/double do napisu, żeby to działało ... – mavnn

0

Nie jest to pełna odpowiedź, ale wydaje się, że stanowi problem podczas aktualizacji. Dodałem trochę dalsze debugowania kodu w procesie wstawiania który generuje następujący (przykład jednym rzędzie aktualizowany):

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] 

Ta ostatnia wartość w każdym ... „wstawiony” linia jest wynikiem nazywając rs.Fields [i] .Value przed wywołaniem polecenia rs.Update(). Linia "Po ..." pokazuje wyniki wywołania rs.Fields [i]. Wartość po wywołaniu polecenia rs.Update().

Co jest jeszcze bardziej denerwujące, to to, że nie jest to niezawodne. Ponowne uruchamianie dokładnie ten sam kod na tej samej rejestruje kilka minut później generowane:

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] 

Jak widać, wyniki są wiarygodne, dopóki nie popełnić je, a potem ... nie.

Powiązane problemy