如何防止表中某些值的组合,从表中已有的值派生?

时间:2016-04-29 19:47:20

标签: python flask-sqlalchemy

我正在开发一个用于存储和管理任务的Web应用程序,使用Flask-SQLAlchemy与后端进行通信。我想使用表来存储任务对之间的优先级比较,以构造partial ordering。该表将有两列,一列用于较小的元素,另一列用于较大的元素,两列一起构成主键。

到目前为止我的代码看起来像这样:

class PriorityPair(db.Model):
    lesser_id = db.Column(db.Integer, db.ForeignKey('task.id'),
                          primary_key=True)
    lesser = db.relationship('Task', remote_side=[id])
    greater_id = db.Column(db.Integer, db.ForeignKey('task.id'),
                           primary_key=True)
    greater = db.relationship('Task', remote_side=[id])

    def __init__(self, lesser, greater):
        self.lesser = lesser
        self.greater = greater

总而言之,这应该足以满足我对表的要求,但是存在一个问题,即可能会插入不一致的行。假设我有两个任务,A和B.如果任务A的优先级高于任务B,我可以执行以下操作:

pair = PriorityPair(task_b, task_a)
db.session.add(pair)
db.session.commit

并且两者之间的关系将根据需要存储。但是,如果在将来的某个时刻,相反的关系PriorityPair(task_a, task_b)将被插入到表中,那将是不一致的。这两项任务的重要性不会同时大于彼此。

现在我可以在python代码中阻止它,但我想确保DB表本身保证保持一致。是否可以(通过Flask-SqlAlchemy)对表格进行某种约束,这样如果(A,B)已经存在,那么(B,A)会被自动拒绝吗?这样的约束会跨DB后端工作吗?

1 个答案:

答案 0 :(得分:0)

否和否。

这是不可能的。 SqlAlchemy支持CHECK constraints,但检查的表达式是以字符串形式给出的。它需要一个子查询,例如(greater_id, lesser_id) not in (select sub.lesser_id, sub.greater_id from priority_pair as sub)。底层数据库后端将阻止它:

相反,您必须找到其他解决方案,无论是触发器还是仅更改整个模型,这都是我决定做的。