SQLAlchemy,使用检查约束条件

24

我刚开始使用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)

你试过这个吗?你得到了什么错误? - univerio
3个回答

23

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

假设您使用了另一个数据库,您需要在表级别定义约束,类似于以下内容:

from sqlalchemy import Column, Integer, String, ForeignKey, Date, CheckConstraint
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)

14

这是一种有效的语法,但在MySQL中(我假设你正在使用MySQL?)将被忽略。根据SQLAlchemy文档:

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

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


是的,我正在使用MySQL。这可能就是原因。我将使用应用程序级别的构造函数检查。 - mrQWERTY
什么是“应用程序级构造函数检查”? - Sam Redway
MySQL现在支持“检查约束”:https://www.w3schools.com/sql/sql_check.asp - user749127

1

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

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

event.listen(target, identifier, func)

在这种情况下,目标是我的模型(“Post”)和我的列(“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()接受2个位置参数,但给出了4个

现在,您可以通过运行试图将负数设置并提交到该列的函数来测试此功能。这将引发值错误,从而创建所需的约束条件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接