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

如何在SQLAlchemy中处理SQL Server的SQL_VARIANT数据类型?

解决SQL Server SQL_VARIANT类型列的Python读取问题

问题背景

需要通过Python获取SQL Server某张表的全部数据,但表中[fan_attribute.value]列为SQL_VARIANT类型,可存储datetime、int、float等多种数据类型。尝试用String、int、float、datetime等类型映射该列时,均触发如下错误:

sqlalchemy.exc.ProgrammingError: (pyodbc.ProgrammingError) ('ODBC SQL type -150 is not yet supported. column-index=6 type=-150', 'HY106')

相关代码

SQL Server建表语句:

create table table_name(
[fan_attribute.value] sql_variant NULL
);

Python代码(原尝试):

from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base

from datetime import datetime
from sqlmodel import Field, PrimaryKeyConstraint, SQLModel

Base = declarative_base()

class ModelName(Base):
    __table_args__ = ({"schema": "can't disclose"})
    __tablename__ = "table_name"
    value = Column("fan_attribute.value", String)

解决方案

方法1:查询时将SQL_VARIANT转为字符串并按需转换

直接在SQL语句中把sql_variant列转换为字符串,同时可通过SQL_VARIANT_PROPERTY获取原始类型,再转换为对应Python类型:

from sqlalchemy import create_engine, text
from datetime import datetime

engine = create_engine("mssql+pyodbc://user:password@dsn_name")

with engine.connect() as conn:
    result = conn.execute(text("""
        SELECT 
            [fan_attribute.value] AS raw_value,
            SQL_VARIANT_PROPERTY([fan_attribute.value], 'BaseType') AS base_type
        FROM table_name
    """))
    for row in result:
        raw_val = row.raw_value
        base_type = row.base_type
        # 根据原始类型转换为对应Python类型
        if base_type == 'int':
            val = int(raw_val)
        elif base_type in ('datetime', 'smalldatetime'):
            val = raw_val  # pyodbc会自动转为datetime对象
        elif base_type in ('float', 'real'):
            val = float(raw_val)
        else:
            val = str(raw_val)
        print(val, type(val))

方法2:自定义SQLAlchemy类型处理SQL_VARIANT

创建自定义类型,让SQLAlchemy能兼容sql_variant类型的解析:

from sqlalchemy.types import TypeDecorator, VARCHAR
import pyodbc
from sqlalchemy import create_engine, Column
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

class SQLVariant(TypeDecorator):
    impl = VARCHAR
    cache_ok = True

    def process_result_value(self, value, dialect):
        # 返回pyodbc处理后的原始值,保留类型信息
        return value

Base = declarative_base()

# 修改Model定义
class ModelName(Base):
    __table_args__ = ({"schema": "can't disclose"})
    __tablename__ = "table_name"
    value = Column("fan_attribute.value", SQLVariant)

# 执行查询
engine = create_engine("mssql+pyodbc://user:password@dsn_name")
Session = sessionmaker(bind=engine)
session = Session()

rows = session.query(ModelName).all()
for row in rows:
    print(row.value, type(row.value))

内容的提问来源于stack exchange,提问作者Sameer Goel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 08:42:18