使用pyodbc从Python应用程序向Access 2003数据库插入值
我之前在StackOverflow上查了很多问题,基本上都能找到我想要的答案,但这次我遇到的情况让我很困惑,所以我决定问问大家。
我其实不是个程序员,只是在工作中提到过Python,现在我有了一个Python项目。起初我觉得一切都还不错,但在往数据库里插入数据时,我就搞不定了。
基本问题:
我用Python和tkinter做了一个表单。当我点击表单上的一个按钮时,我希望能把一些值插入到数据库里。
具体情况:
我使用的是Python 3.4,pyodbc,还有一个Access 2003数据库。
这个数据库里只有一个表,叫做file_info,里面有以下字段,字段的数据类型在后面列出:
ID | 自动编号
filename | 文本
date | 日期/时间
batch_amount | 数字
parcel_amount | 数字
sum_amount | 数字
最终我想插入一些在其他函数中计算出来的值,但现在我只是想通过一个函数插入一些固定的值,可是一直没能成功。
连接字符串:
db_file = r'''C:\Users\amarquart\Documents\testlockboxdb.mdb'''
user = 'admin'
password = ''
odbc_conn_str = 'DRIVER={Microsoft Access Driver (*.mdb,
*.accdb)};DBQ=%s;UID=%s;PWD=%s' % \
(db_file, user, password)
conn = pyodbc.connect(odbc_conn_str)
cur = conn.cursor()
程序编译和运行都没问题,所以我猜测错误不是出在连接字符串上。以下是我在函数中使用的一些代码示例,但都没有成功。
def insert_data():
sql = '''INSERT INTO file_info
(
[ID],
[date],
[filename],
[batches_amount],
[parcels_amount],
[sum_amount],
)
VALUES
(
'1',
'test',
'8/01/2014 1:00:00 PM',
'1',
'1',
'1',
);'''
cur.execute(sql)
conn.commit()
cur.commit()
conn.close()
这段代码给出了这个错误:
在Tkinter回调中出现异常
追踪(最近的调用在最前面):
文件 "C:\Python34\lib\tkinter__init__.py",第1487行,在 call 中
返回 self.func(*args)
文件 "C:/Users/amarquart/PycharmProjects/Grid testing/Source/Grid testing.py",第170行,在 run 中
insert_data()
文件 "C:/Users/amarquart/PycharmProjects/Grid testing/Source/Grid testing.py",第36行,在 insert_data 中
cur.execute(sql)
pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC Microsoft Access Driver] INSERT INTO 语句中的语法错误。(-3502) (SQLExecDirectW)')
def insert_data():
sql = ("""INSERT INTO [file_info] ([ID], [date], [filename], [batches_amount],
[parcels_amount], [sum_amount])
VALUES (?, ?, ?, ?, ?, ?)""", [1, '8/01/2014 1:00:00 PM', 'test', 10, 4, 2])
cur.execute(sql)
conn.commit()
cur.commit()
conn.close()
这段代码给出的错误:
在Tkinter回调中出现异常
追踪(最近的调用在最前面):
文件 "C:\Python34\lib\tkinter__init__.py",第1487行,在 call 中
返回 self.func(*args)
文件 "C:/Users/amarquart/PycharmProjects/Grid testing/Source/Grid testing.py",第154行,在 run 中
insert_data()
文件 "C:/Users/amarquart/PycharmProjects/Grid testing/Source/Grid testing.py",第20行,在 insert_data 中
cur.execute(sql)
TypeError: execute 的第一个参数必须是字符串或Unicode查询。
def insert_data():
sql = """
INSERT INTO file_info (ID, date, filename, batches_amount, parcels_amount, sum_amount)
VALUES (1, '8/01/2014 1:00:00 PM', 'test', 2, 2, 2)
"""
cur.execute(sql)
conn.commit()
cur.commit()
conn.close()
这段代码给出的错误和上一个一样。
def insert_data():
cur.execute("INSERT INTO file_info VALUES (AutoNumber, Text, Date/Time, Number,
Number, Number)",
(1, 'test', '8/01/2014 1:00:00 PM', 2, 2, 2))
conn.commit()
cur.commit()
conn.close()
这段代码给出的错误:
在Tkinter回调中出现异常
追踪(最近的调用在最前面):
文件 "C:\Python34\lib\tkinter__init__.py",第1487行,在 call 中
返回 self.func(*args)
文件 "C:/Users/amarquart/PycharmProjects/Grid testing/Source/Grid testing.py",第153行,在 run 中
insert_data()
文件 "C:/Users/amarquart/PycharmProjects/Grid testing/Source/Grid testing.py",第19行,在 insert_data 中
(1, 'test', '8/01/2014 1:00:00 PM', 2, 2, 2)
pyodbc.ProgrammingError: ('SQL中没有参数标记,但提供了6个参数', 'HY000')
我猜我尝试的所有方法都非常不正确,所以任何帮助都会非常感激。
谢谢大家。
编辑:
根据第一次回复的新尝试,唯一的不同是我使用了三重引号,因为代码跨越了两行。
cur.execute("""INSERT INTO file_info (ID, date, filename, batches_amount,
parcels_amount, sum_amount)
VALUES (1, 'test', '8/01/2014 1:00:00 PM', 2, 2, 2)""")
conn.commit()
这段代码给出的错误:
在Tkinter回调中出现异常
追踪(最近的调用在最前面):
文件 "C:\Python34\lib\tkinter__init__.py",第1487行,在 call 中
返回 self.func(*args)
文件 "C:/Users/amarquart/PycharmProjects/Grid testing/Source/Grid testing.py",第19行,在 insert_data 中
VALUES (1, 'test', '8/01/2014 1:00:00 PM', 2, 2, 2)''')
pyodbc.ProgrammingError: ('42000', '[42000] [Microsoft][ODBC Microsoft Access Driver] INSERT INTO 语句中的语法错误。(-3502) (SQLExecDirectW)')
params = [(1, '8/01/2014 1:00:00 PM', 'test', 2, 2, 2)]
cur.executemany("""insert into file_info(ID, date, filename, batch_amount,
parcel_amount, sum_amount)
values (?, ?, ?, ?, ?, ?)""", params)
conn.commit()
这段代码给出的错误:
在Tkinter回调中出现异常
追踪(最近的调用在最前面):
文件 "C:\Python34\lib\tkinter__init__.py",第1487行,在 call 中
返回 self.func(*args)
文件 "C:/Users/amarquart/PycharmProjects/Grid testing/Source/Grid testing.py",第20行,在 insert_data 中
values (?, ?, ?, ?, ?, ?)""", params)
pyodbc.Error: ('HYC00', '[HYC00] [Microsoft][ODBC Microsoft Access Driver] 未实现的可选功能 (106) (SQLBindParameter)')
2 个回答
你的顺序有点问题:值应该放在列定义之后,插入的值之前,比如在你的例子中:
cur.execute("INSERT INTO file_info (ID, filename, [date], batches_amount, parcels_amount, sum_amount)
VALUES (1, 'test', '8/01/2014 1:00:00 PM', 2, 2, 2)")
conn.commit()
这是标准的SQL插入语法,不仅仅适用于pyodbc或Access。注意,你也可以使用占位符(?)来表示值,然后提供一个值的数组,具体可以查看文档,特别是executemany部分。
另外要注意,你只需要调用conn.commit(),而不是cur.commit(),详细信息可以参考这些其他文档中的插入部分。
编辑:根据beargle的评论,你确实需要把date放在[]里,因为它是一个保留字,这一点在你最初的尝试中是对的,但你把date和filename的值搞反了。尽量避免使用保留字作为字段名,这一点在其他数据库中也适用,不仅仅是Access。
你在几次尝试中已经很接近了。Date
在 Access 中是一个保留字,所以在列名周围加上方括号,并确保列的顺序和数值的顺序一致:
...
sql = """
INSERT INTO file_info (ID, [date], filename, batches_amount, parcels_amount, sum_amount)
VALUES (1, '8/01/2014 1:00:00 PM', 'test', 2, 2, 2)
"""
cur.execute(sql)
....
根据Gord下面的评论,Access 支持带参数的查询,所以理想的代码应该是:
....
params = (1, '8/01/2014 1:00:00 PM', 'test', 2, 2, 2)
sql = """
INSERT INTO file_info (ID, [date], filename, batches_amount, parcels_amount, sum_amount)
VALUES (?, ?, ?, ?, ?, ?)
"""
cur.execute(sql, params)
...