2013-05-08 3 views
0

Новичок пользователя python здесь. Есть другие способы добиться этого, но я считаю, что это мой лучший вариант. Я поддерживаю базу данных MS Access 2007 (.accdb), которая используется на офлайн-планшетных ПК в поле для сбора данных. При возвращении в офис пользователь может повторно подключиться к серверу. Я пытаюсь использовать модуль pyodbc для циклического преобразования таблиц и строк и вставки записей из автономной базы данных в базу данных «master» сервера. Часть выбора скрипта, похоже, работает, чтобы захватить записи в автономной полевой базе данных и помещать их в словарь для последующего использования. Рекомендации, основанные на исходном сообщении, теперь имеют фрагмент вставки через словарь и создают SQL-код на основе параметров для вставки записей. Тем не менее, код вызывает следующую ошибку после того, как две записи будут вставлены в первую таблицу в цикле. Следующая строка sql для следующей таблицы - так что все записи вставляются в первую таблицу правильно и возникает ошибка при переходе к следующей таблице.Репликация таблиц базы данных .accdb с помощью python pyodbc

Error: ('HY010', '[HY010] [Microsoft][ODBC Driver Manager] Function sequence error (0) (SQLFetch)') 

Я прочитал информацию об ошибке здесь, но не знаю, что сделать из него: http://msdn.microsoft.com/en-us/library/windows/desktop/ms712424(v=vs.85).aspx

import pyodbc 

otherDbaseDict = {} 

connOtherDbase = pyodbc.connect(("Driver={Microsoft Access Driver (*.mdb, *.accdb)};" 
           "DBQ=C:\\other.accdb;")) 
otherDbaseTables = connOtherDbase.cursor().tables() 

counter = 0 

for tblOther in otherDbaseTables: 
    if tblOther.table_name.startswith("tbl"): #ignores MS sys tables 
     nameOther = tblOther.table_name 
     cursor = connOtherDbase.cursor() 
     selectSQL = 'SELECT * FROM {}'.format(nameOther) #generate SQL select syntax 
     cursor.execute(selectSQL) 
     rows = cursor.fetchall() 
     for row in rows: 
      counter = counter + 1 #counter digit used to create unique key, since table names repeat 
      otherDbaseDict.update({nameOther+str(counter):row}) 

connMainDbase = pyodbc.connect(("Driver={Microsoft Access Driver (*.mdb, *.accdb)};" 
           "DBQ=C:\\main.accdb;")) 
mainDbaseTables = connMainDbase.cursor().tables() 

#beargle2 
for tblMain in mainDbaseTables: 
    if tblMain.table_name.startswith("tbl"): 
     nameMain = tblMain.table_name 
     # get all column names with list comprehension 
     columns = [row.column_name for row in cursor.columns(table=nameMain)] 
     for k, v in otherDbaseDict.iteritems(): 
      if nameMain in k: 
       # build dynamic sql 
       sql = 'INSERT into {0}({1}) values ({2})' 
       # add question mark placeholders, one for each column 
       # value to insert 
       sql = sql.format(nameMain, ','.join(columns), 
           ','.join(len(columns) * '?')) 
       #print sql 
       cursor = connMainDbase.cursor() 
       # execute parameterized insert 
       cursor.execute(sql, v) 
       connMainDbase.commit() 

Любые указатели на пути примирить ошибку? Просто подумал, это проблема курсора? Нужно ли мне «перезагружать/обновлять» или что угодно, что может быть вызвано после каждого connMainDbase.commit() или перед переключением таблиц? Выполните штампы после завершения первой таблицы. Заглядывая в него, но комментарии приветствуются ...

ответ

1

ПрограммированиеError происходит потому, что у вас есть как одиночные, так и двойные кавычки вокруг строки insertSQL.

Причина, по которой у вас есть только одно поле, заключается в том, что вы все еще находитесь в блоке цикла for, который добавляет имена полей в список. Вы должны Unindent перед тем построения insertSQL строки, так что ваши последние несколько строк должны быть:

for row in cursor.columns(table=nameMain): 
    fieldName = str(row.column_name) 
    fields.append(fieldName) 
insertSQL = 'INSERT into {0}({1}) values ({2})'.format(nameMain,fields,v) 
cursor.execute(insertSQL) 
connMainDbase.commit() 

Однако, что до сих пор не собирается дать вам правильный SQL, потому что у вас есть имена полей в одинарные кавычки и квадратные скобки, и двойные круглые скобки вокруг ваших значений. Я думаю, что самый простой способ исправить это, чтобы преобразовать список по & кортежа натягивает первым:

insertSQL = 'INSERT into {0}({1}) values ({2})'.format(nameMain,', '.join(fields),', '.join(v)) 

Наконец, это лучшая практика, чтобы передать свои ценности методы execute как параметры так, чтобы использовать параметризованный запрос (его может не иметь большого значения в вашем случае использования, но вы также можете следовать лучшей практике). Для этого вам нужно иметь? вместо каждого значения, которое нужно добавить к запросу, которое вы можете сделать, заменив ' ,'.join(v) на ' ,'.join('?'*len(v)) и передав кортеж v в качестве второго аргумента execute.

Вы должны закончить с:

for row in cursor.columns(table=nameMain): 
    fieldName = str(row.column_name) 
    fields.append(fieldName) 
    insertSQL = 'INSERT into {0}({1}) values ({2})'.format(nameMain,', '.join(fields),', '.join('?'*len(v))) 
cursor.execute(insertSQL, v) 
connMainDbase.commit()