【问题标题】:Insert a row with default value column in sqlalchemy在 sqlalchemy 中插入具有默认值列的行
【发布时间】:2020-04-02 22:12:19
【问题描述】:

我正在编写一个程序,它使用以 sqlalchemy 作为客户端的数据库。

这是我的一张桌子

class DownloadRecord(Base):
    __tablename__ = "DownloadRecords"
    id = Column("Id", Integer, primary_key=True, autoincrement=True)

    download_name = Column("DownloadName", Unicode, nullable=False)
    download_date = Column(
        "DownloadDate", DateTime, default=datetime.datetime.utcnow, nullable=False
    )

download_date 列在此处和服务器端表中均使用默认值定义。这是mssql服务器上列的定义

DownloadDate DATETIME NOT NULL DEFAULT GETDATE()

但是我尝试添加记录 DownloadRecord(download_name="new_download_name") 并得到以下异常。

sqlalchemy.exc.IntegrityError: (pyodbc.IntegrityError) ('23000', "[23000] [Microsoft][SQL Server Native Client 11.0][SQL Server]不能 将值 NULL 插入列“DownloadDate”,表 '下载记录';列不允许空值。插入失败。 (515) (SQLExecDirectW); [23000] [Microsoft][SQL Server 本机客户端 11.0][SQL Server]语句已终止。 (3621)") [SQL: 插入 [DownloadRecords] ([DownloadName], [DownloadDate]) 输出 插入。[Id] VALUES (?, ?)] [参数:("new_download_name", None)]

我还尝试使此列可以为空,但是当我添加新行时,DownloadDate 列为空。 如何让它自动使用默认值?

【问题讨论】:

    标签: python sql-server sqlalchemy


    【解决方案1】:

    搜索我发现一些人使用server_default argument 修复。但这使得数据库服务器负责分配值。

    download_date = Column(
        "DownloadDate", DateTime, server_default=text('NOW()'), nullable=False
    )
    

    同样根据SQLAlchemy documentation,ColumnDefault 类是等效的,它也可以工作:

    download_date = Column(
        "DownloadDate", DateTime, ColumnDefault(datetime.datetime.utcnow()), nullable=False
    )
    

    但是,这使用标量而不是可调用对象。

    希望它有效。

    【讨论】:

      【解决方案2】:

      问题是列DownloadDate 的类型与您在客户端作为其默认值提供的值的类型不兼容。

      您使用的类型是DateTime(在服务器端和客户端)。

      但是,在下面的代码中:

      Column("DownloadDate", DateTime, default=datetime.datetime.utcnow, nullable=False)
      

      datetime.datetime.utcnow() 的返回值是一个时区感知对象,而 SQL Server 的 DateTime 不是。

      我看到了两种可能的解决方案:

      1. 将默认值更改为可调用,该可调用返回不支持时区的datetime 对象。

      2. DownloadDate 列的类型更改为时区感知类型。您可以在服务器端使用 SQL Server 的 datetimeoffset,在客户端使用 SQLAlchemy 的 DATETIMEOFFSET

      查看Microsoft's docs on date and time types 以获得完整参考。

      另一方面,考虑迁移到代码优先设计,您可以在一个地方定义架构。

      【讨论】:

      • datetime.datetime.utcnow() 不返回感知日期时间对象:“这类似于 now(),但返回当前 UTC 日期和时间,作为 naive 日期时间对象。”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-19
      • 1970-01-01
      • 1970-01-01
      • 2017-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多