使用Pyodbc插入2003 MDB文件时出现语法错误

时间:2019-02-01 13:25:18

标签: python ms-access

我正在尝试从头开始编写2003 mdb文件。我已经有一个带有表和列名的文件(我有112列)。在尝试中,我从pandas DataFrame中读取了行(在我的代码中命名为节),并将这些行附加到mdb文件中。但是,当使用pyodbc INSERT INTO语法时,它给了我这个错误:

  

ProgrammingError :(“ 42000”,“ [42000] [Microsoft] [Driver ODBC Microsoft Access]表达式语法错误“ Equatorial-TB-BG-CA_IRI-1.0_SNP-1.0_ACA-0_ESAL-1000”。(-3100) (SQLExecDirectW)“)

这是我的代码:

for k in range(len(sections)):
    cols = tuple(list(sections.columns))
    vals = tuple(list(sections.iloc[k]))
    action = 'INSERT INTO SECTIONS {columns} VALUES {values}'.format(columns = str(cols).replace("'",""), values = str(vals).replace("'",""))
    cursor.execute(action)
    conn.commit()

有人知道我为什么会遇到这种问题吗?

1 个答案:

答案 0 :(得分:1)

实际上,这不是特定于Access的错误,而是一般的SQL错误,其中您的字符串文字没有正确地用引号引起来。因此,Access引擎假定它们是命名字段,并被连字符所复杂化,在这些字符中,引擎假定您正在运行减法表达式。

为演示该问题,请参见下文填写您的未知值。请注意,在VALUES中传递的字符串项未加引号:

sections_columns = ['database', 'tool']
cols = tuple(list(sections_columns))

sections_vals = ['ms-access', 'pandas']
vals = tuple(list(sections_vals))

action = 'INSERT INTO SECTIONS {columns} VALUES {values}'.\
          format(columns = str(cols).replace("'",""), values = str(vals).replace("'",""))

print(action)
# INSERT INTO SECTIONS (database, tool) VALUES (ms-access, pandas)

现在,您可以保留在str(vals)中替换的单引号:

action = 'INSERT INTO SECTIONS {columns} VALUES {values}'.\
          format(columns = str(cols).replace("'",""), values = str(vals))

print(action)
# INSERT INTO SECTIONS (database, tool) VALUES ('ms-access', 'pandas')

但更好的是,考虑使用qmark占位符对查询进行参数化并将值作为参数(cursor.execute(query, params)的第二个参数)传递。这样可以避免引号或取消引号的字符串或数字值:

# MOVED OUTSIDE LOOP AS UNCHANGING OBJECTS
cols = tuple(sections.columns)            # REMOVED UNNEEDED list()
qmarks = tuple(['?' for i in cols])       # NEW OBJECT

action = 'INSERT INTO SECTIONS {columns} VALUES {qmarks}'.\
          format(columns = str(cols).replace("'",""), qmarks = str(qmarks))
# INSERT INTO SECTIONS (col1, col2, col3, ...) VALUES (?, ?, ?...)

for k in range(len(sections)):        
    vals = list(sections.iloc[k])         # REMOVED tuple()

    cursor.execute(action, vals)          # EXECUTE PARAMETERIZED QUERY
    conn.commit()

更好的是,避免使用准备好的语句与executemany中的DataFrame.values.tolist()进行循环:

# PREPARED STATEMENT
cols = tuple(sections.columns)
qmarks = tuple(['?' for i in cols])

action = 'INSERT INTO SECTIONS {columns} VALUES {qmarks}'.\
          format(columns = str(cols).replace("'",""), qmarks = str(qmarks))

# EXECUTE PARAMETERIZED QUERY
cursor.executemany(action, sections.values.tolist())   
conn.commit()