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

Python使用pymssql读取SQL Server日期列返回十六进制值问题

问题根因

你库中trnDate列是SQL Server的datetimeoffset类型(从存储值带+04:00时区偏移就能判断),低版本pymssql没有内置对该类型的自动转换逻辑,会直接返回数据库传输的原始二进制字节串。
你之前尝试的加charset参数、pandas端设置parse_dates都没用:前者只解决字符编码问题,和二进制日期类型无关;后者拿到的已经是字节串,根本匹配不到日期字符串格式,自然解析失败。其余列读取正常,是因为那些列的类型都在pymssql默认支持的转换范围内。

可行解决方案

按操作成本从低到高排序:

  • 方案一:查询时显式转换列类型(无需升级、无需额外写转换逻辑,推荐优先用)
    不要直接用select *,在SQL语句里把datetimeoffset类型的trnDate转成pymssql能识别的datetime2类型即可,示例代码:
    import pymssql
    import pandas as pd
    conn = pymssql.connect(server, user, password, "HecPoll5")
    query_sql = """
    SELECT 
      TID, Number,
      CAST(trnDate AS datetime2) AS trnDate,
      LiveMandatorID, Quantity, CustomerID
    FROM dbo.v_beeah_data WHERE customerid=379691
    """
    df = pd.read_sql_query(query_sql, conn)
    
    如果需要保留原列的时区信息,可以把列转成ISO格式字符串再交给pandas解析,把上面SQL里的CAST部分换成CONVERT(VARCHAR, trnDate, 127) AS trnDate,再给read_sql_query加parse_dates=['trnDate']参数即可。
  • 方案二:升级pymssql到最新版本
    新版pymssql已经补上了datetimeoffset类型的自动解析支持,升级后原代码不用任何修改就能正常读取日期。升级命令:
    pip install --upgrade pymssql
    
  • 方案三:读取后手动转换二进制值
    既不想改SQL也不想升级驱动的话,可以拿到DataFrame后按SQL Server datetimeoffset的二进制存储结构手动解析,代码如下:
    from datetime import datetime, timedelta, timezone
    
    def parse_datetimeoffset(raw_bytes):
        time_ticks = int.from_bytes(raw_bytes[:8], byteorder="little")
        offset_min = int.from_bytes(raw_bytes[8:10], byteorder="little", signed=True)
        dt = datetime(1, 1, 1) + timedelta(microseconds=time_ticks // 10)
        return dt.replace(tzinfo=timezone(timedelta(minutes=offset_min)))
    
    df["trnDate"] = df["trnDate"].apply(parse_datetimeoffset)
    

内容的提问来源于stack exchange,提问作者ALIHABIB.IN

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:09:10