Python中使用cx_Oracle查询数据库时,如何解决NUMBER类型字段精度与数据库不符的问题?
小弟在用 cx_Oracle 查询数据库的时候,有的时候查询出来的结果数字精度会莫名其妙的不对劲儿,例如,数据库中存的是 1503.87 ,字段类型为 number(16,2),而通过 cx_Oracle 查询出来的结果却是 1503.8700000000001,请问怎么能让结果正常显示呢?谢谢大家~
Python中使用cx_Oracle查询数据库时,如何解决NUMBER类型字段精度与数据库不符的问题?
1 回复
遇到cx_Oracle里NUMBER字段精度对不上的问题,我猜你是指查询结果里数字的小数位数或者整数部分位数和数据库里定义的不一样,比如数据库里是NUMBER(10,2),但Python里拿到个浮点数,看起来精度丢了。
这问题核心在于cx_Oracle默认把NUMBER映射成Python的float,而float是二进制浮点数,本身就有精度限制和表示问题。要解决它,得让cx_Oracle把NUMBER映射成能保持精度的类型,比如decimal.Decimal。
最直接的办法是在创建连接或游标时设置输出类型处理器。下面是个完整例子:
import cx_Oracle
import decimal
# 首先,定义一个类型处理器
def number_to_decimal(cursor, name, default_type, size, precision, scale):
# 如果精度和标度不为None,就返回decimal类型
if precision is not None and scale is not None:
return cursor.var(decimal.Decimal, arraysize=cursor.arraysize,
outconverter=lambda v: v if v is None else decimal.Decimal(str(v)))
# 建立连接
dsn = cx_Oracle.makedsn("host", "port", service_name="service")
connection = cx_Oracle.connect(user="username", password="password", dsn=dsn)
# 创建游标,并设置输出类型处理器
cursor = connection.cursor()
cursor.outputtypehandler = number_to_decimal
# 执行查询
cursor.execute("SELECT your_number_column FROM your_table")
rows = cursor.fetchall()
for row in rows:
print(row) # 现在row[0]应该是decimal.Decimal类型,保持了精度
cursor.close()
connection.close()
如果你用的是cx_Oracle 8.0或更高版本,还有个更简单的方法,可以直接设置outputtypehandler为decimal.Decimal:
cursor.outputtypehandler = lambda cursor, name, default_type, size, precision, scale: \
cursor.var(decimal.Decimal, arraysize=cursor.arraysize) if default_type == cx_Oracle.NUMBER else None
这样处理之后,查询结果里的NUMBER字段就会以decimal.Decimal对象返回,完全保持数据库里定义的精度和标度,不会出现浮点数精度丢失的问题。
总结:用输出类型处理器把NUMBER映射到decimal.Decimal。

