我刚开始使用sqlalchemy,我想在我的一个列上设置检查约束。我有一个名为startTime
和endTime
的列,我想确保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)
答案 0 :(得分:4)
这是一个有效的语法,但在MySQL中(我假设您使用的是MySQL?),这将被忽略。来自sqla docs:
>检查约束可以命名或未命名,可以使用CheckConstraint构造在Column或Table级别创建。检查约束的文本直接传递到数据库,因此存在有限的“数据库独立”行为。列级检查约束通常应仅引用它们所在的列,而表级约束可引用表中的任何列。 请注意,某些数据库不主动支持检查约束,例如MySQL。
您可以创建一个触发器,但是然后您将业务逻辑放到数据库层。我会编写一个app-level构造函数检查。
答案 1 :(得分:0)
除了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 :(得分:0)
创建检查约束的另一种方法是使用SQLAlchemy的event.listen
事件API。
在用例中,我想在模型上创建列检查,其中列不能为负数。
event.listen(target, identifier, func)
在这种情况下,目标是我的模型(“发布”)和我的列(“支持”)。在这种情况下,标识符为“设置”。在这种情况下,该函数是在我的模型中创建的静态方法。所以看起来像这样:
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”,value是我们将列属性设置为的值。注意:在event.listen中使用的函数需要4个参数,我不确定为什么这样,如果有人有原因请发表评论。没有4个参数(仅将目标值和值作为args),我得到了错误TypeError: before_set_upvotes() takes 2 positional arguments but 4 were given
。
现在,您可以通过运行一个试图为该列设置并提交负数的函数来进行测试。将会产生值错误,从而创建我们需要的约束。