You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何设置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 10:05:27