Frage

In MSSQL 2005 schlug ich nur die berüchtigte Fehlermeldung:

  

FOREIGN KEY-Einschränkung auf Tabelle XXX YYY Einführung kann Zyklen oder mehrere kaskadenWege verursachen. Angeben LÖSCHEN auf die NO ACTION oder ON UPDATE NO ACTION oder ändern anderen FOREIGN KEY-Einschränkungen.

Nun hat mehrere Themen Stackoverflow zu dieser Fehlermeldung, so dass ich habe schon die Lösung (in meinem Fall werde ich Trigger verwenden müssen), aber ich bin neugierig, warum gibt es ein solches Problem überhaupt .

Wie ich es verstehe, gibt es grundsätzlich zwei Szenarien, die sie vermeiden wollen - ein Zyklus und mehrere Pfade. Ein Zyklus wäre, wo zwei Tabellen haben kaskadierende Fremdschlüssel miteinander. OK, kann ein Zyklus zu mehreren Tabellen erstrecken, aber dies ist der Grundfall und wird einfacher zu analysieren.

Mehrere Pfade wären, wenn TableA Fremdschlüssel TableB und TableC hat, und TableB hat auch einen Fremdschlüssel zu TableC. Wieder -. Dies ist der Mindestgrund Fall

Ich kann keine Probleme sehen, die entstehen würde, wenn ein Datensatz in einer dieser Tabellen erhalten gelöscht oder aktualisiert würden. Sicher, Sie könnten die gleichen Tabelle mehrere Male abfragen müssen, um zu sehen, welche Datensätze müssen Aktualisierung / Löschen, aber ist das wirklich ein Problem? Ist das ein Performance-Problem?

In anderen SO Themen Menschen so weit gehen, wie mit Kaskaden zu beschriften „ riskant " und erklärt, dass "

Andere Tipps

Der Grund, warum wir Kaskade löschen verbieten verwendet, hat mit Leistung und Verriegelung zu tun. Ja, es ist nicht so schlecht, wenn man einen Datensatz löschen, aber früher oder später müssen Sie eine große Gruppe von Datensätzen und Ihre Datenbank wird zum Stillstand kommt löschen.

Wenn Sie genügend Datensätze löschen, kann SQL Server zu einer Tabellensperre eskalieren, und niemand kann mit der Tabelle nichts tun, bis es fertig ist.

Wir zogen vor kurzem eine unseres Kunden zu seinem eigenen Server. Im Rahmen der Transaktion auch hatten wir dann alle, dass Kunden Datensätze löschen unseren ursprünglichen Server bilden. Löscht alle seine Informationen in Chargen (um nicht zu Problemen mit anderen Nutzern) dauerte ein paar Monate. Wenn wir Kaskade löschen aufgestellt hatte, hätte die Datenbank zu den anderen Kunden für eine lange Zeit nicht zugänglich gewesen, wie Millionen von Datensätzen wurden in einer Transaktion gelöscht und Hunderte von Tabellen wurden gesperrt, bis die Transaktion durchgeführt wurde.

Ich könnte auch ein Szenario sehen, wo ein Deadlock Kaskade löschen, da wir keine Kontrolle über den Auftrag haben, würde die Kaskade Weg genommen haben aufgetreten könnte bei der Verwendung hat und unsere Datenbank ist etwas denormalized mit clientid in den meisten Tabellen erscheint. Also, wenn es die eine Tabelle gesperrt, die auch als auch die Client-Tabelle zu einer dritten Tabelle einen Fremdschlüssel hatte, die in einem Differnt Weg war, es könnte möglicherweise nicht die Tabelle, um den Check aus der dritten Tabelle zu löschen, weil das alles ist, eine Transaktion und die Sperren nicht, bis es fertig wurde freigegeben. Also vielleicht wäre es nicht lassen Sie uns einrichten Kaskade löscht, wenn es die Möglichkeit der Schaffung von Deadlocks in der Transaktion sieht.

Ein weiterer Grund Kaskadierung zu vermeiden löscht ist, dass manchmal die Existenz eines Kindes Rekord ist Grund genug, nicht den übergeordneten Datensatz zu löschen. Zum Beispiel, wenn Sie eine Kundentabelle haben und dass Kundenaufträge hatten in der Vergangenheit, würden Sie nicht wollen, ihn zu löschen und die Informationen über die tatsächliche Reihenfolge verlieren.

eine Tabelle der Mitarbeiter vor:

CREATE TABLE Employee
(
    EmpID   INTEGER NOT NULL PRIMARY KEY,
    Name    VARCHAR(40) NOT NULL,
    MgrID   INTEGER NOT NULL REFERENCES Employee(EmpID) ON DELETE CASCADE
);

INSERT INTO Employees(     1, "Bill",   1);
INSERT INTO Employees(    23, "Steve",  1);
INSERT INTO Employees(234212, "Helen", 23);

Nehmen wir nun an Bill Ruhestand:

DELETE FROM Employees WHERE Name = "Bill";

Ooooppps; jeder bekam nur entlassen!

[ Wir können darüber diskutieren, ob die Einzelheiten der Syntax korrekt sind; das Konzept steht, denke ich. ]

Ich denke, das Problem ist, dass, wenn Sie einen Weg machen „ON DELETE CASCADE“ und die anderen „ON DELETE RESTRICT“, oder „keine Aktion“ das Ergebnis (das Ergebnis) ist unpredicable. Es hängt davon ab, welche Lösch-Trigger (dies ist auch ein Auslöser, aber man Sie nicht selbst bauen müssen) wird zuerst ausgeführt werden.

Ich stimme mit, dass die Kaskaden „riskant“ zu sein und sollte vermieden werden. (Ich persönlich bevorzuge die Änderungen Kaskadierung manuell vielmehr, dass mit SQL Server automatisch um sie kümmern). Dies auch, weil selbst wenn SQL Server Millionen von Zeilen gelöscht, noch die Ausgabe als

zeigen würde

(1 Zeile (n) betroffen)

denke ich, ob eine ON DELETE CASCADE-Option verwenden, um eine Frage des Geschäftsmodells ist, dass Sie implementieren. Eine Beziehung zwischen zwei Business-Objekten könnte entweder ein einfacher „Verein“, wo beide Ende der Beziehung verwendet sind, aber ansonsten unabhängige Objekte des Lebenszyklus von denen von anderer Logik verschieden ist und gesteuert werden. Es gibt aber auch „Aggregation“ Beziehungen, wo ein Objekt könnte in der Tat als „Eltern“ zu sehen oder „Besitzer“ ein „Kind“ oder „Detail“ Objekt. Es ist der noch stärkere Begriff einer „Komposition“ Beziehung, wo ein Objekt nur als Zusammensetzung einer Anzahl von Teilen besteht. In der „Verein“ Fall Sie wird in der Regel nicht erklären, eine EIN-CASCADE-Einschränkung DELETE. Für Aggregationen oder Zusammensetzungen jedoch DELETE die ON CASCADE hilft Ihnen, Abbildung Ihrer Geschäftsmodell in der Datenbank genauer und in einer deklarativen Weise. Aus diesem Grund ist es ärgert mich, dass MS SQL Server die Verwendung dieser Option auf einen einzelnen Kaskaden Pfad beschränkt. Wenn mich nicht alles täuscht, viele andere weit verbreitete SQL-Datenbanksysteme nicht solche Beschränkungen auferlegen.

scroll top