如何设置PYODBC返回Decimal类型并避免科学计数法(无需转换类型)
解决PYODBC读取SQL Server decimal(24,12)时返回科学计数法Decimal的问题
当使用PYODBC从SQL Server读取decimal(24, 12)类型的数据时,值0.000000000000会被返回为Python的decimal.Decimal('0E-12'),写入CSV文件时直接显示为0E-12,而非预期的0.000000000000或0。
现有解决方案(非最优)
目前常见的处理方式是通过字符串转换规避,但都需要额外的转换开销:
Python端处理
通过格式化Decimal为指定精度的字符串:
import pyodbc import decimal import csv cn = ... # 初始化数据库连接 cr = cn.cursor() cr.execute("SELECT MyColumn, ... FROM MyView") data = cr.fetchall() cols = [desc[0] for desc in cr.description] with open(csv_path, mode='w', newline='') as csv_f: csv_writer = csv.writer(csv_f, delimiter=",", quotechar='"', quoting=csv.QUOTE_NONNUMERIC) csv_writer.writerow(cols) for r in data: for (i, c) in enumerate(cr.description): if c[1] == decimal.Decimal: d, scale = r[i], c[5] r[i] = f"{d:{scale}f}" csv_writer.writerows(data)
T-SQL端处理
在查询时直接转换为字符串:
import pyodbc cn = ... # 初始化数据库连接 cr = cn.cursor() cr.execute("SELECT convert(varchar(24), MyColumn) as MyColumn, ... FROM MyView") data = cr.fetchall()
更高效的原生Decimal处理方案
目前PYODBC没有公开的配置项直接控制Decimal的返回格式(该问题源于ODBC驱动对decimal类型的序列化逻辑),但可以利用Decimal的原生方法quantize()和normalize()来处理,避免字符串转换的额外开销,同时保留Decimal类型的优势:
import pyodbc import decimal import csv # 设置Decimal精度匹配SQL的decimal(24,12) decimal.getcontext().prec = 24 # 定义目标精度,对应12位小数 target_scale = decimal.Decimal('1.' + '0'*12) cn = ... # 初始化数据库连接 cr = cn.cursor() cr.execute("SELECT MyColumn, ... FROM MyView") data = cr.fetchall() cols = [desc[0] for desc in cr.description] with open(csv_path, mode='w', newline='') as csv_f: csv_writer = csv.writer(csv_f, delimiter=",", quotechar='"', quoting=csv.QUOTE_NONNUMERIC) csv_writer.writerow(cols) for r in data: for (i, c) in enumerate(cr.description): if c[1] == decimal.Decimal: d = r[i] # 归一化后按目标精度格式化,将0E-12转为0.000000000000 r[i] = d.normalize().quantize(target_scale) csv_writer.writerows(data)
这种方式会将decimal.Decimal('0E-12')转换为decimal.Decimal('0.000000000000'),写入CSV时会显示为预期的格式,同时保留Decimal类型的特性,CSV模块的引号处理逻辑依然适用,性能比字符串转换更优。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

