【问题标题】:SQLAlchemy and SQL Server Datetime field overflowSQLAlchemy 和 SQL Server 日期时间字段溢出
【发布时间】:2019-07-14 08:03:59
【问题描述】:

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

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

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

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

datetime.datetime(214, 7, 21, 0, 0)

...那是 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)

我现在将其更新为:

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)

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

【问题讨论】:

  • 这里至少还有一份关于 ODBC 处理日期/时间类型问题的报告:developercommunity.visualstudio.com/content/problem/281326/…
  • 那么我试图做的事情是不可能的吗?
  • 我不能肯定。您可以控制 SQL 数据库吗?然后,人们可能会想方设法解决这个问题。
  • 是的,我可以控制 SQL 数据库。
  • 您是否按照 Alexander Volok 的建议更改为原生 SQL Server 客户端?我相信这实际上可以解决问题。

标签: python sql-server sqlalchemy


【解决方案1】:

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

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

datetime T-SQL:

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

另一个原因,似乎是问题的根源,与 ODBC 和 DATETIME2 有关: error 22008: Datetime field overflow when inserting a record with datetime2 field via ODBC

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

所以看起来像 ODBC,从发布 SQL Server 2008 开始,在内部更改了 DATETIME2 的比例。

我建议听从this thread 的建议,从 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)

【讨论】:

  • 我在数据库中使用 datetime2,所以它应该能够记录 214 年。是的,它看起来像一个错误(并且可能是)但我仍然需要能够插入进入数据库。我的问题是 datetime.datetime(214, 7, 21, 0, 0) 是由 sqlalchemy 生成的,我问是否有任何方法可以强制它使用四位数的年份值。我认为这是 db 表所需要的。
  • 我怀疑 SLQAlchemy 只是试图传递一个 DATETIME 值,而不是一个 DATETIME2...
  • 可能是这样,只需要知道如何更改它,并且在互联网上找不到任何表明您可以的地方。
  • 我已经用 ODBC 相关问题更新了我的答案。
  • 将我的连接字符串更改为 connectionString = 'mssql+pyodbc://username:password@my_server/my_database_name?driver=SQL Server Native Client 11.0' 工作(我没有安装 10.0,但是11.0)。谢谢您的帮助。很好的发现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多