pyodbc驱动类型转换配置:解决含Null的int列被pandas转为float问题
解决方案
完全可以通过pyodbc的自定义输出转换器功能,在驱动层完成空值填充,不需要修改SQL语句,也不需要在pandas读取数据后做二次处理。
核心原理
pandas会把包含None的int列自动转为float的根本原因:原生pyodbc返回SQL类型为int的NULL值时,会映射为Python的None值,而pandas默认的int dtype不支持存储空值,只能向上转型为float存储NaN。我们只要在pyodbc将数据返回给上层调用方(pandas)之前,就把int类型的NULL替换为指定的整数占位值,返回的所有值都是int类型,pandas读取后自然会保留int dtype。
具体实现步骤
- 第一步:确定要处理的SQL整数类型对应的pyodbc编码,常用整数类型对应关系如下:
- 普通int对应
pyodbc.SQL_INTEGER - bigint对应
pyodbc.SQL_BIGINT - smallint对应
pyodbc.SQL_SMALLINT
- 普通int对应
- 第二步:编写自定义转换函数,实现空值填充逻辑
import pyodbc import pandas as pd # 自定义int空值转换器,可根据业务需求把NULL替换为0、-1等不会和正常业务值冲突的占位值 def int_null_converter(value): if value is None: # 这里改成你需要的默认填充值 return 0 return int(value)
- 第三步:建立数据库连接后,给当前连接注册自定义转换器
# 连接串按你实际的数据库配置修改即可 conn = pyodbc.connect("DRIVER={ODBC Driver 17 for SQL Server};SERVER=你的服务器地址;DATABASE=你的库名;UID=账号;PWD=密码") # 绑定转换器和对应SQL类型,需要处理哪种整数类型就加对应的绑定规则 conn.add_output_converter(pyodbc.SQL_INTEGER, int_null_converter) # 如需处理bigint取消注释下行 # conn.add_output_converter(pyodbc.SQL_BIGINT, int_null_converter) # 如需处理smallint取消注释下行 # conn.add_output_converter(pyodbc.SQL_SMALLINT, int_null_converter)
- 第四步:正常调用pandas.read_sql读取存储过程即可,无需额外参数
# 存储过程调用语句按你的实际需求修改 df = pd.read_sql("EXEC 你的存储过程名 参数1,参数2", con=conn)
注意事项
- 填充用的占位值要选择业务逻辑里不会出现的数值,避免和正常数据混淆,比如业务值都是正整数的场景,用-1做占位符比0更稳妥。
- 转换器仅对当前注册的连接生效,每次新建连接都需要重新注册一次。
- 如果后续需要区分原始空值和正常数值,只要判断对应列是否等于你设置的占位值即可。
内容的提问来源于stack exchange,提问作者ALTAF HUSSAIN
相关产品推荐
相关产品推荐

