将Polars数据写入SQL Server时遇类型转换错误求助
问题:Polars写入SQL Server时datetime字段抛出DataError
我有个Python脚本,从CSV读取数据后写入SQL Server临时表,使用Polars添加了process_time字段:
data = data.with_columns( ( pl.datetime( year=current_date.year, month=current_date.month, day=current_date.day, hour=current_date.hour, minute=current_date.minute, second=current_date.second, ) ).alias("process_time"), )
SQL表对应的字段定义:
... [process_time] [datetime] NULL, ...
执行polars.to_sql()时抛出报错:
DataError: (pyodbc.DataError) ('22018', '[22018] [Microsoft][ODBC Driver 17 for SQL Server]Invalid character value for cast specification (0) (SQLExecute)')
手动导入处理后的文件时,SQL Server提示process_time字段可能存在数据丢失。
困惑点:这段逻辑上月运行正常,本月无代码变更却报错。已确认无空行、NULL值,process_time每行值完全一致,用Polars的unique()方法确认类型是datetime[μs],值为2023-11-08 14:21:33。
补充信息:转成Pandas后查看唯一值:
<ArrowExtensionArray> [Timestamp('2023-11-08 15:57:45')] Length: 1, dtype: timestamp[us][pyarrow]
Polars版本信息:
--------Version info--------- Polars: 0.19.12 Index type: UInt32 Platform: Windows-10-10.0.19045-SP0 Python: 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)] ----Optional dependencies---- adbc_driver_sqlite: <not installed> cloudpickle: <not installed> connectorx: <not installed> deltalake: <not installed> fsspec: <not installed> gevent: <not installed> matplotlib: <not installed> numpy: 1.26.1 openpyxl: <not installed> pandas: 2.1.2 pyarrow: 13.0.0 pydantic: <not installed> pyiceberg: <not installed> pyxlsb: <not installed> sqlalchemy: 2.0.22 xlsx2csv: <not installed> xlsxwriter: <not installed>
排查思路与解决方案
1. 时间精度不匹配导致类型转换失败
SQL Server的datetime类型仅支持毫秒级精度(3位小数),而你的Polars时间字段是微秒级(6位小数)。即使显示的时间值没有小数位,底层存储的微秒精度在与ODBC驱动交互时,可能被解析为带冗余小数的格式,导致SQL Server无法完成转换。
解决方法:将Polars的datetime字段强制转换为毫秒精度:
data = data.with_columns( pl.col("process_time").cast(pl.Datetime(time_unit="ms")) )
2. 修复Polars to_sql的类型映射问题
Polars的to_sql依赖SQLAlchemy或pyodbc做类型映射,特定版本组合下可能存在微秒datetime到SQL Server datetime的映射bug。可以尝试两种方式:
- 显式指定SQL类型:在
to_sql中通过dtype参数明确字段类型
from sqlalchemy import DateTime data.to_sql( "your_temp_table", your_db_connection, dtype={"process_time": DateTime()}, # 其他参数(如if_exists、index等)保持原有配置 )
- 转Pandas后写入:绕开Polars的类型映射逻辑,直接用Pandas的
to_sql
data.to_pandas().to_sql( "your_temp_table", your_db_connection, dtype={"process_time": DateTime()}, # 其他参数保持原有配置 )
3. 排查依赖版本变更
即使代码未修改,依赖包可能自动更新导致兼容性问题:
- 检查ODBC Driver 17 for SQL Server是否有更新,尝试回滚到上月可用版本
- 核对pyarrow、SQLAlchemy版本是否与上月一致,当前你使用pyarrow 13.0.0、SQLAlchemy 2.0.22,若之前版本不同,可尝试降级测试
4. 清理临时表元数据缓存
SQL Server的临时表可能存在元数据缓存,尝试先删除临时表再重新创建,或更换临时表名称测试,避免旧元数据干扰。
内容的提问来源于stack exchange,提问作者E Leo
相关产品推荐
相关产品推荐

