Ermitteln von Verweisadressen auf das SQLAlchemy-Objekt

8

Ich habe viele Model-Klassen mit Beziehungen zwischen ihnen mit einer CRUD-Schnittstelle zu bearbeiten. Das Problem besteht darin, dass einige Objekte nicht gelöscht werden können, da andere Objekte auf sie verweisen. Manchmal kann ich eine ON DELETE-Regel einrichten, um diesen Fall zu behandeln, aber in den meisten Fällen möchte ich nicht automatisch verwandte Objekte löschen, bis sie manuell gelöst werden. Wie auch immer, ich möchte dem Redakteur eine Liste von Objekten vorstellen, die sich auf das aktuell angezeigte beziehen, und diejenigen hervorheben, die das Löschen aufgrund der FOREIGN KEY-Einschränkung verhindern. Gibt es eine fertige Lösung, um Referer automatisch zu erkennen?

Aktualisieren

Die Aufgabe scheint sehr häufig zu sein (z. B. django ORM zeigt alle Abhängigkeiten), so dass ich mich wundere, dass es noch keine Lösung dafür gibt.

Es gibt zwei Richtungen vorgeschlagen:

  1. Zählen Sie alle Beziehungen des aktuellen Objekts auf und durchlaufen Sie deren backref . Aber es gibt keine Garantie, dass alle Relationen backref definiert haben. Darüber hinaus gibt es Fälle, in denen backref bedeutungslos ist. Obwohl ich es überall definieren kann, mag ich es nicht so und es ist nicht zuverlässig.
  2. (Vorgeschlagen von van und stephan) Prüfe alle Tabellen von MetaData object und sammle Abhängigkeiten von ihrer foreign_keys Eigenschaft (der Code von sqlalchemy_schemadisplay kann als Beispiel verwendet werden, dank stephans Kommentaren. Dies ermöglicht es, alle Abhängigkeiten zwischen -Tabellen zu erfassen, aber was ich brauche, sind Abhängigkeiten zwischen Modellklassen . Einige Fremdschlüssel sind in Zwischentabellen definiert und weisen keine ihnen entsprechenden Modelle auf (in Beziehungen als secondary verwendet). Klar, ich kann weiter gehen und verwandtes Modell finden (muss noch einen Weg finden, es zu tun), aber es sieht zu kompliziert aus.

Lösung

Unten ist eine Methode der Basismodellklasse (für die deklarative Erweiterung), die ich als Lösung verwende. Es ist nicht perfekt und erfüllt nicht alle meine Anforderungen, aber es funktioniert für den aktuellen Stand meines Projekts. Das Ergebnis wird als Wörterbuch von Wörterbüchern gesammelt, sodass ich sie nach Objekten und ihren Eigenschaften gruppiert darstellen kann. Ich habe noch nicht entschieden, ob es eine gute Idee ist, da die Liste der Referer manchmal riesig ist und ich gezwungen bin, sie auf eine vernünftige Anzahl zu beschränken.

%Vor%

Danke an alle, die mir geholfen haben, besonders an Stephan und van.

    
Denis Otkidach 17.02.2010, 10:37
quelle

3 Antworten

6

SQL: Ich stimme absolut nicht mit S.Lott ' Antwort . Ich kenne keine Out-of-the-Box-Lösung, aber es ist definitiv möglich , alle Tabellen zu ermitteln, die ForeignKey-Einschränkungen für eine bestimmte Tabelle haben. Man muss die INFORMATION_SCHEMA Ansichten wie REFERENTIAL_CONSTRAINTS , KEY_COLUMN_USAGE , TABLE_CONSTRAINTS usw. richtig verwenden. Siehe SQL Server-Beispiel . Mit einigen Einschränkungen und Erweiterungen unterstützen die meisten Versionen neuer relationaler Datenbanken INFORMATION_SCHEMA standard. Wenn Sie alle FK-Informationen und das Objekt (Zeile) in der Tabelle haben, müssen einige SELECT -Anweisungen ausgeführt werden, um alle anderen Zeilen in anderen Tabellen zu erhalten, die sich auf die angegebene Zeile beziehen und verhindern, dass sie gelöscht wird. p>

SqlAlchemy: Wie von stephan in seinem Kommentar erwähnt, sollte es ziemlich einfach für Sie sein, wenn Sie orm mit backref für Relationen verwenden die Liste der übergeordneten -Objekte, die den Verweis auf das Objekt behalten, das Sie löschen möchten, da diese Objekte grundsätzlich zugeordnete Eigenschaften Ihres Objekts sind ( child1.Parent ).

Wenn Sie mit Table Objekten von sql alchemy arbeiten (oder nicht immer backref für Relationen verwenden), müssten Sie Werte von foreign_keys für alle Tabellen und dann für all diese ForeignKey erhalten s Rufen Sie references(...) method auf und stellen Sie Ihre Tabelle als Parameter zur Verfügung. Auf diese Weise finden Sie alle FKs (und Tabellen), die sich auf die Tabelle beziehen, der Ihr Objekt zugeordnet ist. Dann können Sie alle Objekte abfragen, die auf Ihr Objekt verweisen, indem Sie die Abfrage für jede dieser FKs erstellen.

    
van 17.02.2010, 12:50
quelle
1

Im Allgemeinen gibt es keine Möglichkeit, alle der Referenzen in einer relationalen Datenbank zu entdecken.

In einigen Datenbanken können sie deklarative referenzielle Integrität in Form von expliziten Fremdschlüssel- oder Prüfbedingungen verwenden.

Aber das ist nicht erforderlich. Es kann unvollständig oder inkonsistent sein.

Jede Abfrage kann eine FK-Beziehung enthalten, die nicht deklariert ist. Ohne das Universum aller Abfragen können Sie nicht wissen, welche Beziehungen verwendet, aber nicht deklariert werden.

Um "Referer" im Allgemeinen zu finden, müssen Sie das Datenbankdesign kennen und alle Abfragen haben.

    
S.Lott 17.02.2010 10:53
quelle
0

Für jede Modellklasse können Sie leicht sehen, ob alle ihre Eins-zu-Viele-Beziehungen leer sind, indem Sie einfach nach der Liste fragen und sehen, wie viele Einträge sie enthält. (Es gibt wahrscheinlich auch einen effizienteren Weg, der in Bezug auf COUNT implementiert wird.) Wenn es Fremdschlüssel für das Objekt gibt und Sie Ihre Objektbeziehungen korrekt eingerichtet haben, dann wird mindestens eine dieser Listen ungleich Null sein in Länge.

    
Kylotan 17.02.2010 11:20
quelle

Tags und Links