3

我在 MS Access 中有一个数据库。我正在尝试使用 pypyodbc 向 Python 查询一张表。我收到以下错误消息:

ValueError:无法将字符串转换为浮点数:E+6

表中的数字相当大,最多有十位有效数字。错误消息告诉我 MSAccess 正在以科学记数法格式化它们,而 Python 正在将它们作为字符串读取。

表中的字段格式为带两位小数的单项。当我在数据库中看到表格中的数字时,它们没有使用科学计数法进行格式化。但错误消息似乎表明它们是。

此外,如果我将表中的数字(至少对于测试行)更改为小数字(从 1 到 5 的整数),则查询运行。这支持了我的理论,即问题是大数字的科学格式。

关于如何:

  1. 以不以科学计数法格式化数字的方式写入数据库表,或
  2. 让 pypyodbc 像这样检索数字并忽略任何科学记数法。
4

3 回答 3

4

从or字段(列)中检索“大”或“小”数字时,这似乎是和 Access ODBC 驱动程序之间的兼容性问题,其中“大”表示SingleDouble

  • Single小数点左侧有效数字超过 6 位的值,或
  • Double小数点左侧超过 14 位有效数字的值

“小”是指

  • Single小数点右侧有超过 6 个零的值,或
  • Double小数点右侧有超过 14 个零的值

当数字表示为“正常”小数时(即,不是科学计数法)。

重新创建的代码:

import pypyodbc
cnxn = pypyodbc.connect(
    r"DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};"
    r"DBQ=C:\Users\Public\Database1.accdb")
crsr = cnxn.cursor()
try:
    crsr.execute("DROP TABLE tblJunk")
except pypyodbc.ProgrammingError as pe:
    # ignore "table does not exist"
    if pe.value[0] != '42S02':
        raise
crsr.execute("CREATE TABLE tblJunk (ID INT PRIMARY KEY, DoubleField DOUBLE, SingleField SINGLE)")
crsr.execute("INSERT INTO tblJunk (ID, DoubleField) VALUES (1, 12345678.9)")
crsr.execute("SELECT DoubleField, SingleField FROM tblJunk WHERE ID=1")
row = crsr.fetchone()
print(row)
# prints: (12345678.9, None)
crsr.execute("UPDATE tblJunk SET SingleField = DoubleField WHERE ID=1")
crsr.execute("SELECT DoubleField, SingleField FROM tblJunk WHERE ID=1")
row = crsr.fetchone()
# ValueError: could not convert string to float: E+7

解决方法1:对于Single值,使用该CDbl()函数可以避免错误:

crsr.execute("SELECT DoubleField, CDbl(SingleField) AS foo FROM tblJunk WHERE ID=1")
row = crsr.fetchone()
print(row)
# prints: (12345678.9, 12345679.0)

解决方法 2:使用该CStr()函数将值作为字符串返回,然后将其转换为浮点数(适用于SingleDouble):

crsr.execute("SELECT DoubleField, CStr(SingleField) AS foo FROM tblJunk WHERE ID=1")
row = crsr.fetchone()
print(row)
# prints: (12345678.9, u'1.234568E+07')
print(float(row[1]))
# prints: 12345680.0

解决方法 3:使用而不是 pypyodbc。

于 2015-11-24T18:06:37.500 回答
0

As I was putting together test files for you to try to reproduce, I noticed that two of the fields in the table were set to Single type rather than Double. Changed them to Double and that solved the problem. Sorry for the bother and thanks for the help.

于 2015-11-24T13:03:28.877 回答
0

除了 Gord 的回答之外,如果您不介意失去一些浮点精度,我建议第四种可能的解决方法,就像我的情况一样。

实际上,无论如何我都应该这样做以减少我的数据框大小,因为 6 位小数对于我的 pandas 计算来说已经绰绰有余了......所以我只是在我的 SQL 查询中使用了Round()函数:

SELECT Round(my_field,6) AS rounded_field FROM mytable

至于错误的根源,我的有问题的字段是latitudeand longitude(以定义为“双倍自动小数位数”的度数存储)。但它们是通过从整数++的 VBA 转换来计算的,这有时会导致重复出现的十进制数

15º 30' 40'' 导致:15 + 30/60 + 40/60/60 = 15.51111111111...

...并通过Round(x,6)转换,成为15.511111我的数据框中。

如果我不想失去精度,那么我宁愿将原始数字存储在我的数据库表中,而不是将它们转换为浮点数。

于 2021-12-19T17:45:20.660 回答