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

使用Pyodbc连接SQL Server时百万级数值读取异常问题排查

问题原因分析
  1. 表值函数逻辑问题:首先确认SQL Server中函数返回的原始值——如果dbo.my_func内部将百万级数值除以1000后返回,就会导致读取后数值变为千级。
  2. PyODBC驱动数值转换异常:部分ODBC驱动默认配置会对decimal/numeric类型进行自动缩放,导致大数值被错误缩小1000倍。
  3. Pandas自动类型推断错误:Pandas在读取时误判列类型,或因浮点精度问题导致数值被意外缩放。
解决方法

1. 排查函数原始输出

在SSMS中执行以下查询,确认STOCK_AMOUNT的真实值:

SELECT STOCK_AMOUNT FROM dbo.my_func('35214')
  • 若结果为7226而非7226000,直接修改函数代码,确保返回未缩放的原始数值。

2. 定位问题环节(PyODBC vs Pandas)

跳过Pandas,用PyODBC直接读取数值,判断问题出在驱动还是框架:

import pyodbc

# 替换为你的连接字符串
conn_str = "DRIVER={ODBC Driver 17 for SQL Server};SERVER=your_server;DATABASE=your_db;UID=user;PWD=pass"
conn = pyodbc.connect(conn_str)
cursor = conn.cursor()

cursor.execute("SELECT STOCK_AMOUNT FROM dbo.my_func('35214')")
for row in cursor.fetchall():
    print(f"读取值: {row.STOCK_AMOUNT}, 类型: {type(row.STOCK_AMOUNT)}")

conn.close()
  • 若输出正确(如7226000),问题在Pandas;若输出为7226,问题在PyODBC驱动或数据库配置。

3. 调整PyODBC连接参数

若PyODBC读取错误,修改连接字符串,强制驱动保留原始精度:

conn_str = "DRIVER={ODBC Driver 17 for SQL Server};SERVER=your_server;DATABASE=your_db;UID=user;PWD=pass;DecimalAsNumeric=Yes;NumericAsDecimal=Yes"

4. 显式指定Pandas列类型

若问题在Pandas的自动推断,读取时用Decimal类型保证精确性(Windows支持):

from decimal import Decimal
import pandas as pd

df = pd.read_sql_query(
    "SELECT * FROM dbo.my_func('35214')",
    conn,
    dtype={"STOCK_AMOUNT": Decimal}
)

# 按需转换为浮点型
df["STOCK_AMOUNT"] = df["STOCK_AMOUNT"].astype(float)

5. 处理字符串格式的数值

如果STOCK_AMOUNT是带单位的字符串(如7.226M),手动解析转换:

def parse_stock_amount(val):
    val = val.strip().upper()
    if val.endswith('M'):
        return float(val[:-1]) * 1_000_000
    elif val.endswith('K'):
        return float(val[:-1]) * 1_000
    return float(val)

df["STOCK_AMOUNT"] = df["STOCK_AMOUNT"].apply(parse_stock_amount)

内容的提问来源于stack exchange,提问作者Tugrul Gokce

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 16:25:35