In Konflikt stehende CASCADE und Fremdschlüssel Anforderungen einstelle?
-
20-08-2019 - |
Frage
Ich arbeite an einer Datenbank, die Dateien und Abhängigkeiten in Projekten verfolgt. Kurz gesagt, ich habe zwei Haupttabellen; Die Projekte Tabelle listet Namen und andere Eigenschaften projizieren, listet die Dateien Tabellendateien. Jeder Dateieintrag verweist auf ein Projekt als Fremdschlüssel zu CASCADE eingestellt, so dass, wenn ich ein Projekt Datensatz aus der Datenbank löschen, werden alle Dateieinträge verschwinden auch. So weit, so gut.
Jetzt habe ich einen zusätzlichen DEPENDENCIES Tisch. Jeder Datensatz in der Abhängigkeitstabelle ist zwei Dateien, die Angabe, dass die erste Datei auf dem zweiten abhängt. Wieder sind diese Fremdschlüssel wird die erste auf CASCADE eingestellt (also wenn ich eine Datei Eintrag löschen, dieser Datensatz gelöscht wird), aber der zweite Satz ist zu beschränken (so einen Dateieintrag zu löschen, wenn alle anderen Dateien, die ich bin nicht abhängig erlaubt darauf). Auch hier scheint alles gut.
Leider scheint es, ich kann nicht mehr ein Projekt mit einem einzigen SQL-Anweisung löschen löschen! Der Lösch versucht, die Dateien in Kaskade löschen, aber wenn irgendetwas davon in der DEPENDENCIES Tabelle angezeigt, die einstelle Fremdschlüssel den Lösch verhindert (obwohl dieser Datensatz in der Tabelle Abhängigkeiten entfernt werden, da die andere Säule CASCADE ist). Die einzige Abhilfe, die ich habe, ist eine genaue Reihenfolge zu berechnen, die Dateien so dass keiner der Abhängigkeit Rekord Einschränkungen verletzt werden zu löschen und entfernen Sie eine Datei der Aufzeichnungen zu einem Zeitpunkt, bevor das Projekt zu entfernen.
Gibt es eine Möglichkeit, meine Datenbankschema einzurichten so dass eine einzelne SQL aus der Tabelle Projekte löschen, werden die anderen Löschungen richtig kaskadieren? Ich bin mit Firebird 2.1, aber ich weiß nicht, ob das einen Unterschied macht - es scheint, wie es sollte ein Weg, um diese Arbeit zu machen
Lösung
Sie können nicht die Reihenfolge der Löschung durch eine Kaskadierung von Fremdschlüssel steuern, aber Sie können einen Trigger auf PROJECTS
entwerfen können, Zeilen in FILES
zu löschen, die zu diesem Projekt gehören und auch in DEPENDENCIES
als abhängig von anderen FILES
aufgelistet . Machen Sie es einen BEFORE DELETE
Trigger, also sollte es vor den Kaskadeneffekte auszuführen.
So etwas wie folgt aus:
CREATE TRIGGER Del_Child_Files FOR PROJECTS
BEFORE INSERT
AS BEGIN
FOR SELECT F.FILE_ID FROM FILES F JOIN DEPENDENCIES D
ON F.FILE_ID = D.CHILD_ID
WHERE F.PROJECT_ID = OLD.PROJECT_ID
INTO :file_id
DO
DELETE FROM FILES WHERE FILE_ID = :file_id;
DONE
END
So Wenn Sie ein Projekt löschen, dies löscht alle „Kind“ Dateien eines Projektes, das auf anderen Dateien abhängig ist, und diese Kaskaden Reihen in DEPENDENCIES
zu löschen, so dass alle verbleibenden Dateien frei von Abhängigkeiten sind. Ihre Löschung des Projekts können nun kaskadieren, diese Dateien zu löschen.
Ich habe nicht getestet und meine Firebird Syntax rostig sein, aber vielleicht wird es Ihnen den Einstieg.
Offensichtlich bitte testen diese auf einer Kopie Ihrer Daten, nicht die Live-Daten!
Andere Tipps
Unterstützt das System latente Zwänge, in denen die Bedingungsprüfung, bis eine COMMIT-Punkt verschoben werden kann?
Vielleicht ist das nur eine Oracle-Sache aber.