2016-04-29 8 views
1

Ich entwickle eine Web-App zum Speichern und Verwalten von Aufgaben unter Verwendung von , um mit dem Backend zu sprechen. Ich möchte eine Tabelle verwenden, um Prioritätsvergleiche zwischen Aufgabenpaaren zu speichern, um eine partial ordering zu erstellen. Die Tabelle wird zwei Spalten haben, eine für das kleinere Element und eine für das größere Element, und beide Spalten bilden zusammen den Primärschlüssel.Wie kann ich bestimmte Kombinationen von Werten in einer Tabelle verhindern, die von den bereits in der Tabelle angegebenen Werten abgeleitet sind?

Mein Code so sieht weit wie folgt aus:

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 

Alles in allem, ist dies für ausreichend sein sollte, was ich mit dem Tisch machen wollen, aber es gibt ein Problem, dass inkonsistente Zeilen eingefügt werden könnten. Angenommen, ich habe zwei Aufgaben, A und B. Wenn Task A von mehr Priorität als Aufgabe B ist, konnte ich folgendes tun:

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

und die Beziehung zwischen den beiden würde gespeichert werden, wie gewünscht. Aber wenn zu einem späteren Zeitpunkt die entgegengesetzte Beziehung, PriorityPair(task_a, task_b), in die Tabelle eingefügt werden würde, wäre das inkonsistent. Die beiden Aufgaben können nicht gleichzeitig wichtiger sein als einander.

Jetzt könnte ich wahrscheinlich dies in Python-Code verhindern, aber ich möchte sicher sein, dass die DB-Tabelle selbst garantiert konsistent bleibt. Ist es möglich (über Flask-SqlAlchemy) eine Art Einschränkung für die Tabelle zu setzen, so dass (A,B) bereits vorhanden ist, dann wird automatisch zurückgewiesen? Und würde solch eine Beschränkung über DB-Backends funktionieren?

+0

Sie könnten wahrscheinlich eine [CHECK-Einschränkung] (http://docs.sqlalchemy.org/en/latest/core/constraints.html#check-constraint) erstellen, die die transitive Eigenschaft der Reihenfolge erzwingt, aber DB-übergreifend Portabilität ist begrenzt. –

+0

@LukasGraf Können Sie das in Form einer Antwort unten setzen? – izrik

+0

Ich habe CHECK Constraints noch nicht für irgendetwas nicht-Trivial verwendet, und mir fehlt derzeit die Zeit und das notwendige Setup, um eine halbwegs anständige Antwort zu schreiben. Aber wenn du herausfinden kannst, wie es für deinen Anwendungsfall funktioniert, werde ich es gerne tun, wenn du es als Selbstantwort postest. –

Antwort

0

Nein und Nein.

Dies ist nicht möglich. SqlAlchemy unterstützt CHECK constraints, aber der Ausdruck der Überprüfung wird als Zeichenfolge angegeben. Es erfordert eine Unterabfrage, etwa (greater_id, lesser_id) not in (select sub.lesser_id, sub.greater_id from priority_pair as sub). Und die zugrunde liegenden Datenbank Backends wird es verhindern:

Stattdessen müssen Sie eine andere Lösung finden, ob es Auslöser ist oder einfach nur das gesamte Modell zu ändern, das ist, was ich zu tun beschlossen.