SQLAlchemy 和 SQL Server 日期时间字段溢出

t_w*_*sop 3 python sql-server sqlalchemy

我正在使用 SQLAlchemy 连接到 SQL Server 数据库。

我试图从 python 脚本将一个对象插入到表中,但失败了。我收到错误:

(pyodbc.DataError) ('22008', '[22008] [Microsoft][ODBC SQL Server Driver]Datetime field overflow (0) (SQLExecDirectW)')
Run Code Online (Sandbox Code Playgroud)

看起来这是由以下日期时间对象引起的:

datetime.datetime(214, 7, 21, 0, 0)
Run Code Online (Sandbox Code Playgroud)

...那是 214 年 7 月 21 日

SQL Server 表中对应的日期时间字段的类型为 datetime2。

看起来从 python/SQLAlchemy 到 SQL Server 的转换并未在年初值中添加“0”。我通过以下事实证实了这一点:我可以使用带或不带前导“0”的 INSERT 语句手动将此日期添加到 SQL Server。

有没有办法强制日期的年份部分采用正确的格式?或者这是由其他原因引起的?

更新:https://docs.sqlalchemy.org/en/latest/dialects/mssql.html我发现您可以将列的类型指定为 DATETIME2 (对于 MS SQL),并且我已经更新了对象映射因此。

所以之前是:

from base import Base
from sqlalchemy import Column, Integer, String, Numeric, DateTime

class Results(Base):
    __tablename__ = 'Result'

    dateTimeMinValue = Column(DateTime)
    dateTimeMaxValue = Column(DateTime)
Run Code Online (Sandbox Code Playgroud)

我现在将其更新为:

from base import Base
from sqlalchemy import Column, Integer, String, Numeric
from sqlalchemy.dialects.mssql import DATETIME2

class Results(Base):
    __tablename__ = 'Result'

    dateTimeMinValue = Column(DATETIME2)
    dateTimeMaxValue = Column(DATETIME2)
Run Code Online (Sandbox Code Playgroud)

但我仍然遇到和以前一样的错误。

Ale*_*lok 5

SQL Server 表中对应的日期时间字段的类型为 datetime2。

SQL Alchemy 是否仍会将该值构建为 DATETIME 类型,而不考虑目标表中的相应类型?

日期时间 T-SQL:

日期范围: 1753年1月1日至9999年12月31日:

另一个原因,似乎是问题的根源,与 ODBC 和 DATETIME2 有关: 错误 22008:通过 ODBC 插入包含 datetime2 字段的记录时,日期时间字段溢出

SQL Server 的早期 ODBC 驱动程序可以根据比例(必须为 0 或 3)推断服务器类型(datetime 或smalldatetime),因此比 SQL Server 2008 Native Client 更轻松。OdbcParameter 的默认小数位数为 0,因此早期的驱动程序可能会假定服务器类型必须为smalldatetime 并忽略任何小数秒。随着 datetime2 和用户定义的 0 到 7 之间的范围的引入,驱动程序无法再从范围推断类型,并且必须默认为最丰富的类型 datetime2。当实际服务器类型不是 datetime2 时,服务器端将进行从 datetime2 到实际服务器类型的转换。对于这给您带来的不便,我深表歉意,但我们别无选择,并且新行为已记录在案。

看来 ODBC,从 SQL Server 2008 版本开始,在内部更改了 DATETIME2 的比例。

我建议遵循此线程的建议并从 ODBC 切换到本机 SQL Server 客户端:

import sqlalchemy as sql
connectionString = 'mssql+pyodbc://username:password@my_server/my_database_name?driver=SQL Server Native Client 10.0'
engine = sql.create_engine(connectionString)
Run Code Online (Sandbox Code Playgroud)