【问题标题】:sqlalchemy, using check constraintssqlalchemy,使用检查约束
【发布时间】:2016-02-25 01:25:43
【问题描述】:

我刚开始使用 sqlalchemy,我想在我的一个列上设置一个检查约束。我有一个名为startTimeendTime 的专栏,我想确保endTime > startTime

from sqlalchemy import Column, Integer, String, ForeignKey, Date
import models.Base

class Session(Base):
    __tablename__ = 'sessions'

    sid = Column(Integer, primary_key=True)
    uid = Column(Integer, ForeignKey('users.uid'), nullable=False)
    startTime= Column(Date, nullable=False)

    #probably won't work
    endTime = Column(Date, CheckConstraint('endTime > startTime'), nullable=False)

【问题讨论】:

  • 你试过了吗?你得到什么错误?

标签: python flask sqlalchemy


【解决方案1】:

除了 MySQL 不支持检查约束这一事实之外,我认为问题在于您试图在列级别检查约束中引用多个列。

假设您使用了另一个数据库,您需要在表级别定义约束,如下所示:

from sqlalchemy import Column, Integer, String, ForeignKey, Date
import models.Base

class Session(Base):
    __tablename__ = 'sessions'
    __table_args__ = (
        CheckConstraint('endTime > startTime'),
    )

    sid = Column(Integer, primary_key=True)
    uid = Column(Integer, ForeignKey('users.uid'), nullable=False)
    startTime= Column(Date, nullable=False)

    endTime = Column(Date, nullable=False)

【讨论】:

    【解决方案2】:

    这是一个有效的语法,但在 MySQL 中(我假设您使用的是 MySQL?)这将被忽略。来自 SQLAlchemy 文档:

    检查约束可以命名或未命名,并且可以使用 CheckConstraint 构造在列或表级别创建。检查约束的文本直接传递到数据库,因此存在有限的“数据库独立”行为。列级检查约束通常应该只引用它们所在的列,而表级约束可以引用表中的任何列。 请注意,某些数据库不主动支持检查约束,例如 MySQL。*

    您当然可以创建触发器,但随后您会将业务逻辑放到数据库层。我会写一个应用程序级的构造函数检查。

    【讨论】:

    • 是的,我正在使用 MySQL。这可能解释了原因。我将使用应用级构造函数检查。
    • 什么是“应用级构造函数检查”?
    【解决方案3】:

    创建检查约束的另一种方法是使用 SQLAlchemy 中的 event.listen 事件 API。

    在我的用例中,我想在我的模型上创建一个列检查,其中列不能是负数。

    event.listen(target, identifier, func)
    

    在这种情况下,目标是我的模型(“发布”)和我的专栏(“upvotes”)。在这种情况下,标识符是“set”。本例中的函数是在我的模型中创建的静态方法。所以它看起来像这样:

    event.listen(Post.upvotes, "set", Post.before_set_upvotes)
    

    我的功能如下:

    @staticmethod
    def before_set_upvotes(target, value, oldvalue, initiator):
        if value < 0:
            raise ValueError('Upvotes cannot be a negative value')
    

    目标参数是“Post.upvotes”,值是我们将列属性设置为的值。注意: event.listen 中使用的函数需要 4 个参数,我不确定为什么,如果有人有理由请评论。如果没有 4 个参数(并且只有目标和值作为参数),我会收到错误 TypeError: before_set_upvotes() takes 2 positional arguments but 4 were given

    现在您可以通过运行一个尝试设置负数并将负数提交到该列的函数来测试这一点。将引发值错误,从而创建我们需要的约束。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-20
      • 2016-02-27
      • 2013-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      相关资源
      最近更新 更多