使用Pyodbc连接SQL Server时百万级数值读取异常问题排查
问题原因分析
- 表值函数逻辑问题:首先确认SQL Server中函数返回的原始值——如果
dbo.my_func内部将百万级数值除以1000后返回,就会导致读取后数值变为千级。 - PyODBC驱动数值转换异常:部分ODBC驱动默认配置会对
decimal/numeric类型进行自动缩放,导致大数值被错误缩小1000倍。 - 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
相关产品推荐
相关产品推荐

