0

新手python用户在这里。还有其他方法可以实现这一点,但我相信这是我最好的选择。我维护了一个 MS Access 2007 数据库 (.accdb),用于在现场的离线 TabletPC 上收集数据。回到办公室后,用户可以重新连接到服务器。我正在尝试利用 pyodbc 模块循环遍历表和行,并将离线字段数据库中的记录插入服务器“主”数据库。脚本的选择部分似乎正在抓取离线字段数据库中的记录并将它们放入字典以供以后使用。基于原始帖子的推荐现在有插入部分循环遍历字典并创建基于参数的 sql 用于插入记录。然而,将两条记录插入循环中的第一个表后,代码将引发以下错误。下一个 sql 字符串用于下一个表 - 因此所有记录都正确插入到第一个表中,并且在移动到下一个表时会发生错误。

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() 之后或切换表之前调用它?一旦完成第一个表,执行就死了。正在研究它,但欢迎评论......

4

1 回答 1

1

发生 ProgrammingError 是因为字符串周围有单引号和双引号insertSQL

您只有一个字段的原因是您仍在for将字段名称添加到列表的循环块中。您需要在构造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()
于 2013-05-08T22:38:26.590 回答