Проблема Вставка данных в базу данных MS Access с помощью ADO через Python - PullRequest
6 голосов
/ 12 марта 2009

[Правка 2: дополнительная информация и отладка в ответе ниже ...]

Я пишу скрипт на python для экспорта баз данных MS Access в серию текстовых файлов, чтобы обеспечить более содержательный контроль версий (я знаю - почему Access? Почему я не использую существующие решения? Скажем так, ограничения не применяются технического характера).

Я успешно экспортировал все содержимое и структуру базы данных с помощью ADO и ADOX через библиотеку comtypes, но у меня возникла проблема с повторным импортом данных.

Я экспортирую содержимое каждой таблицы в текстовый файл со списком в каждой строке, например:

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

И следующая функция для импорта указанного файла:

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

Все работает нормально, за исключением того, что числовые значения (double и int) вставляются в виде нулей. Любые идеи о том, связана ли проблема с моим кодом, eval, comtypes или ADO?

Редактировать: я исправил проблему с вставкой чисел - приведение их в виде строк (!), Кажется, решает проблему как для двойных, так и для целых полей.

Однако теперь у меня есть другая проблема, которая ранее была скрыта из-за вышеизложенного: первое поле в каждой строке устанавливается в 0 независимо от типа данных ... Есть идеи?

Ответы [ 3 ]

4 голосов
/ 12 марта 2009

И нашел ответ.

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

Должно быть:

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

Теперь мне просто нужно разобраться, почему. Просто надеюсь, что этот вопрос спасет кого-то еще на несколько часов ...

0 голосов
/ 12 марта 2009

Пока не полный ответ, но, похоже, это проблема во время обновления. Я добавил дополнительный код отладки в процесс вставки, который генерирует следующее (пример обновления одной строки):

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]

Последнее значение в каждой строке "Inserted ..." является результатом вызова rs.Fields [i] .Value перед вызовом rs.Update (). Строка «After ...» показывает результаты вызова rs.Fields [i] .Value после вызова rs.Update ().

Что еще более раздражает, так это то, что он не дает надежных результатов. Повторный запуск того же кода для тех же записей через несколько минут сгенерировал:

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]

Как видите, результаты надежны до тех пор, пока вы их не совершите, тогда ... нет.

0 голосов
/ 12 марта 2009

data[i] рассматривается как строка? Что произойдет, если вы определите его как int / double при установке rs.Fields[i].Value?

Кроме того, что происходит, когда вы распечатываете содержимое rs.Fields[i].Value после его установки?

...