Wann wird "ON UPDATE CASCADE" verwendet?

420

Ich verwende regelmäßig "ON DELETE CASCADE", aber niemals "ON UPDATE CASCADE", da ich nicht so sicher bin, in welcher Situation es nützlich sein wird.

Zur Diskussion sehen wir uns einen Code an.

CREATE TABLE parent (
    id INT NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (id)
);

CREATE TABLE child (
    id INT NOT NULL AUTO_INCREMENT, parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id)
        REFERENCES parent(id)
        ON DELETE CASCADE
);

Wenn für "ON DELETE CASCADE" ein Elternteil mit einem idgelöscht wird, wird ein Datensatz in einem Kind mit parent_id = parent.idautomatisch gelöscht. Dies sollte kein Problem sein.

  1. Dies bedeutet, dass "ON UPDATE CASCADE" dasselbe tut, wenn iddas übergeordnete Element aktualisiert wird.

  2. Wenn (1) wahr ist, bedeutet dies, dass "ON UPDATE CASCADE" nicht verwendet werden muss, wenn parent.ides nicht aktualisierbar ist (oder niemals aktualisiert wird), wie wenn es ist AUTO_INCREMENToder immer eingestellt ist TIMESTAMP. Ist das richtig?

  3. Wenn (2) nicht wahr ist, in welcher anderen Situation sollten wir "ON UPDATE CASCADE" verwenden?

  4. Was passiert, wenn ich das (aus irgendeinem Grund) so aktualisiere child.parent_id, dass es nicht vorhanden ist? Wird es dann automatisch gelöscht?

Nun, ich weiß, einige der oben genannten Fragen können programmgesteuert getestet werden, um zu verstehen, aber ich möchte auch wissen, ob dies vom Hersteller des Datenbankanbieters abhängt oder nicht.

Bitte werfen Sie etwas Licht.

NawaMan
quelle
1
Siehe auch: stackoverflow.com/questions/6894162/…
Xiè Jìléi

Antworten:

467

Wenn Ihr Primärschlüssel nur ein automatisch inkrementierter Identitätswert ist, haben Sie für ON UPDATE CASCADE keine wirkliche Verwendung.

Angenommen, Ihr Primärschlüssel ist ein 10-stelliger UPC-Barcode. Aufgrund der Erweiterung müssen Sie ihn in einen 13-stelligen UPC-Barcode ändern. In diesem Fall können Sie mit ON UPDATE CASCADE den Primärschlüsselwert ändern, und alle Tabellen mit Fremdschlüsselverweisen auf den Wert werden entsprechend geändert.

In Bezug auf # 4 sollten Sie einen Fremdschlüsselfehler erhalten, wenn Sie die untergeordnete ID in etwas ändern, das in der übergeordneten Tabelle nicht vorhanden ist (und Sie über eine referenzielle Integrität verfügen).

C-Pfund-Guru
quelle
6
Ich musste ON UPDATE CASCADEmich nur benutzen , um Primärschlüssel in einer alten Tabelle zu aktualisieren, die keinen automatisch inkrementierten Schlüssel verwendet
BlueRaja - Danny Pflughoeft
86
  1. Ja, dies bedeutet, dass zum Beispiel, wenn Sie UPDATE parent SET id = 20 WHERE id = 10alle Kinder tun, die parent_id von 10 ebenfalls auf 20 aktualisiert werden

  2. Wenn Sie das Feld, auf das sich der Fremdschlüssel bezieht, nicht aktualisieren, wird diese Einstellung nicht benötigt

  3. Ich kann mir keine andere Verwendung vorstellen.

  4. Sie können dies nicht tun, da die Fremdschlüsseleinschränkung fehlschlagen würde.

Zed
quelle
29

Ich denke, Sie haben die Punkte ziemlich genau getroffen!

Wenn Sie die Best Practices für das Datenbankdesign befolgen und Ihr Primärschlüssel niemals aktualisierbar ist (was meiner Meinung nach sowieso immer der Fall sein sollte), brauchen Sie die ON UPDATE CASCADEKlausel nie wirklich .

Zed machte einen guten Punkt: Wenn Sie einen natürlichen Schlüssel (z. B. ein reguläres Feld aus Ihrer Datenbanktabelle) als Primärschlüssel verwenden, kann es bestimmte Situationen geben, in denen Sie Ihre Primärschlüssel aktualisieren müssen. Ein weiteres aktuelles Beispiel wäre die ISBN (International Standard Book Numbers), die sich vor nicht allzu langer Zeit von 10 auf 13 Ziffern + Zeichen geändert hat.

Dies ist nicht der Fall, wenn Sie Ersatzschlüssel (z. B. künstlich vom System generierte Schlüssel) als Primärschlüssel verwenden (was meine bevorzugte Wahl in allen außer den seltensten Fällen wäre).

Am Ende also: Wenn sich Ihr Primärschlüssel nie ändert, brauchen Sie die ON UPDATE CASCADEKlausel nie .

Marc

marc_s
quelle
Was sind "künstlich vom System generierte" Schlüssel? UUIDs?
HPWD
1
@HPWD: Nur ein "künstlicher" Schlüssel (ein Wert, der nicht auf Ihren tatsächlichen Daten basiert oder von diesen abgeleitet ist), der vom System generiert wird - es kann eine GUID oder eine INT oder eine BIGINT sein - oder irgendetwas wirklich - nicht ist egal. Der Punkt ist: Dieser Wert steht in keiner Beziehung zu Ihren eigenen tatsächlichen Daten - und das System generiert diesen Wert automatisch für Sie.
marc_s
@ marc-s danke, dass du dir die Zeit genommen hast, das aufzuschreiben. Ihre Antwort ergab vollkommen Sinn.
HPWD
2
Eine einspaltige Tabelle mit natürlichen Schlüsseln ist meiner Meinung nach eine gute und saubere Alternative zu Aufzählungen (zumindest in MySQL DB-Varianten). Betrachten wir zum Beispiel eine Tabelle colorsmit Zeilen blue, purple, yellowund eine Tabelle productsmit einer product_colorSpalte, FK'ed zum Sein colorsTisch. Das schränkt die Auswahl wie eine Aufzählung ein, aber im Gegensatz zu einer automatisch inkrementierenden Ganzzahl ist kein Join erforderlich, um den Farbnamen zu erhalten. In einem solchen Fall on update cascadeist eine gute Idee, wenn Sie entscheiden, dass stattdessen purpleaufgerufen violetwerden soll.
Okdewit
18

Vor ein paar Tagen hatte ich ein Problem mit Triggern und ich habe herausgefunden, dass ON UPDATE CASCADEdies nützlich sein kann. Schauen Sie sich dieses Beispiel an (PostgreSQL):

CREATE TABLE club
(
    key SERIAL PRIMARY KEY,
    name TEXT UNIQUE
);

CREATE TABLE band
(
    key SERIAL PRIMARY KEY,
    name TEXT UNIQUE
);

CREATE TABLE concert
(
    key SERIAL PRIMARY KEY,
    club_name TEXT REFERENCES club(name) ON UPDATE CASCADE,
    band_name TEXT REFERENCES band(name) ON UPDATE CASCADE,
    concert_date DATE
);

In meiner Ausgabe musste ich einige zusätzliche Operationen (Trigger) definieren, um die Konzerttabelle zu aktualisieren. Diese Operationen mussten club_name und band_name ändern. Ich konnte es aufgrund von Referenzen nicht tun. Ich konnte das Konzert nicht ändern und mich dann mit Club- und Bandtischen befassen. Ich konnte es auch nicht anders machen. ON UPDATE CASCADEwar der Schlüssel zur Lösung des Problems.

Ariel Grabijas
quelle
3
Guter Kommentar. Ich finde bei Update-Kaskade auch nützlich, auf jeden Fall müssen Sie Ihre ID ändern. Ich stimme auch anderen zu, dass diese Änderung nicht so typisch sein sollte. In dem von Ihnen zitierten Fall denke ich beispielsweise, dass bei großen Datenmengen die Zuordnung von Fremdschlüsseln mithilfe von Textfeldern möglicherweise nicht zu der schnellsten Leistung des Datenbankmoduls führt. Beachten Sie, dass die Änderungen im Namen die Beziehung zwischen den Tischen nicht beeinflussen würden, wenn die Fremdbeziehung im Konzerttisch club.SERIAL und die Band.SERIAL verwendet. Ich finde jedoch, dass ON UPDATE CASCADE ein großartiges Werkzeug zur Lösung von Notfällen ist. Grüße
David L
4
Dies ist jedoch ein fragwürdiges Design, das ein ziemlich ausgeklügeltes Beispiel darstellt. Was bringt es, zwei SERIALSpalten in clubund bandals Primärschlüssel zu belassen, wenn Sie auf names anstelle des Primärschlüssels jeder Tabelle verweisen ?
sm
Kurz gesagt, dies ist nützlich, wenn Sie ein Feld aus einer anderen Tabelle duplizieren und es auf dem neuesten Stand halten müssen.
Kamil Tomšík
4

Mein Kommentar bezieht sich hauptsächlich auf Punkt 3: Unter welchen Umständen gilt ON UPDATE CASCADE, wenn wir davon ausgehen, dass der übergeordnete Schlüssel nicht aktualisierbar ist? Hier ist ein Fall.

Ich habe es mit einem Replikationsszenario zu tun, in dem mehrere Satellitendatenbanken mit einem Master zusammengeführt werden müssen. Jeder Satellit generiert Daten für dieselben Tabellen. Das Zusammenführen der Tabellen mit dem Master führt daher zu Verstößen gegen die Eindeutigkeitsbeschränkung. Ich versuche, ON UPDATE CASCADE als Teil einer Lösung zu verwenden, bei der ich die Schlüssel bei jeder Zusammenführung neu inkrementiere. ON UPDATE CASCADE sollte diesen Prozess vereinfachen, indem ein Teil des Prozesses automatisiert wird.

ted.strauss
quelle
3

Es ist eine ausgezeichnete Frage, ich hatte gestern die gleiche Frage. Ich dachte über dieses Problem nach, speziell SUCHTE, wenn es so etwas wie "ON UPDATE CASCADE" gab, und glücklicherweise hatten die Designer von SQL auch darüber nachgedacht. Ich stimme Ted.strauss zu und habe auch Norans Fall kommentiert.

Wann habe ich es benutzt? Wie Ted betonte, kann, wenn Sie mehrere Datenbanken gleichzeitig behandeln und die Änderung in einer von ihnen in einer Tabelle jede Art von Reproduktion in der von Ted als "Satellitendatenbank" bezeichneten Datenbank aufweist, nicht mit dem Original beibehalten werden ID, und aus irgendeinem Grund müssen Sie eine neue erstellen, falls Sie die Daten der alten nicht aktualisieren können (z. B. aufgrund von Berechtigungen oder wenn Sie in einem so kurzlebigen Fall nach Echtheit suchen verdient nicht den absoluten und völligen Respekt für die totalen Regeln der Normalisierung, einfach weil dies ein sehr kurzlebiger Nutzen sein wird)

Ich stimme also in zwei Punkten zu:

(A.) Ja, in vielen Fällen kann ein besseres Design dies vermeiden. ABER

(B.) Bei Migrationen, Replizieren von Datenbanken oder Lösen von Notfällen ist es ein GROSSARTIGES WERKZEUG, das zum Glück vorhanden war, als ich nach einer Existenz suchte.

David L.
quelle