web-dev-qa-db-ger.com

Wann ist "ON UPDATE CASCADE" zu verwenden?

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

Zur Erörterung sehen wir uns 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 bei "ON DELETE CASCADE" ein übergeordnetes Element mit einem id gelöscht wird, wird ein untergeordneter Datensatz mit parent_id = parent.id Automatisch gelöscht. Das sollte kein Problem sein.

  1. Das bedeutet, dass "ON UPDATE CASCADE" dasselbe tut, wenn id des übergeordneten Elements aktualisiert wird?

  2. Wenn (1) wahr ist, bedeutet dies, dass "ON UPDATE CASCADE" nicht verwendet werden muss, wenn parent.id Nicht aktualisierbar ist (oder niemals aktualisiert wird), wie wenn es AUTO_INCREMENT Oder immer ist setze auf 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 (aus irgendeinem Grund) den child.parent_id Aktualisiere, damit er nicht vorhanden ist? Wird er dann automatisch gelöscht?

Nun, ich weiß, einige der obigen Fragen können programmgesteuert getestet werden, um zu verstehen, aber ich möchte auch wissen, ob dies von einem Datenbankanbieter abhängt oder nicht.

Bitte werfen Sie etwas Licht.

395
NawaMan

Wenn Ihr Primärschlüssel nur ein automatisch inkrementierter Identitätswert ist, kann ON UPDATE CASCADE in Wirklichkeit nicht verwendet werden.

Nehmen wir jedoch an, Ihr Primärschlüssel ist ein 10-stelliger UPC= Strichcode, und aufgrund der Erweiterung müssen Sie ihn in einen 13-stelligen UPC Strichcode ä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.

Wenn Sie in Bezug auf # 4 die untergeordnete ID in eine ID ändern, die in der übergeordneten Tabelle nicht vorhanden ist (und die referenzielle Integrität aufweist), sollte ein Fremdschlüsselfehler auftreten.

444
C-Pound Guru
  1. Ja, es bedeutet, dass zum Beispiel, wenn Sie UPDATE parent SET id = 20 WHERE id = 10 Alle übergeordneten Kinder-IDs von 10 werden ebenfalls auf 20 aktualisiert

  2. Wenn Sie das Feld, auf das sich der Fremdschlüssel bezieht, nicht aktualisieren, ist diese Einstellung nicht erforderlich

  3. Ich kann mir keine andere Verwendung vorstellen.

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

80
Zed

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 meines Erachtens sowieso immer der Fall sein sollte), brauchen Sie die ON UPDATE CASCADE - Klausel nie wirklich.

Zed machte einen guten Punkt, dass, wenn Sie einen natürlichen Schlüssel (z. B. ein reguläres Feld aus Ihrer Datenbanktabelle) als Primärschlüssel verwenden, es bestimmte Situationen geben kann, in denen Sie müssen Ihre Primärschlüssel aktualisieren. 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 Surrogat (z. B. vom System künstlich erzeugte) Schlüssel als Primärschlüssel verwenden (was in allen Fällen, außer in den seltensten Fällen, meine bevorzugte Wahl wäre).

Also am Ende: Wenn sich Ihr Primärschlüssel niemals ändert, brauchen Sie niemals die ON UPDATE CASCADE - Klausel.

Marc

27
marc_s

Vor ein paar Tagen hatte ich ein Problem mit Auslösern, und ich habe herausgefunden, dass ON UPDATE CASCADE kann nützlich sein. 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 nicht tun, weil ich mich darauf bezog. Ich konnte das Konzert nicht modifizieren und mich dann um Club- und Bandtische kümmern. Ich könnte es auch nicht anders machen. ON UPDATE CASCADE war der Schlüssel zur Lösung des Problems.

16
Ariel Grabijas

Mein Kommentar bezieht sich hauptsächlich auf Punkt 3: Unter welchen Umständen ist ON UPDATE CASCADE anwendbar, 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 in denselben Tabellen, sodass das Zusammenführen der Tabellen mit dem Master zu Verstößen gegen die Eindeutigkeitsbeschränkung führt. Ich versuche, ON UPDATE CASCADE als Teil einer Lösung zu verwenden, bei der ich die Schlüssel bei jedem Zusammenführen erneut inkrementiere. ON UPDATE CASCADE sollte diesen Prozess vereinfachen, indem ein Teil des Prozesses automatisiert wird.

4
ted.strauss

Es ist eine ausgezeichnete Frage, ich hatte gestern die gleiche Frage. Ich habe über dieses Problem nachgedacht, insbesondere darüber, ob etwas wie "ON UPDATE CASCADE" existiert, 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 man bei der gleichzeitigen Bearbeitung mehrerer Datenbanken und der Änderung einer dieser Datenbanken in einer Tabelle, die in einer von Ted als "Satellitendatenbank" bezeichneten Art reproduziert wird, nicht das Original beibehalten ID, und aus irgendeinem Grund müssen Sie eine neue erstellen, falls Sie die Daten auf der alten nicht aktualisieren können (z. B. aufgrund von Berechtigungen oder falls Sie in einem so kurzlebigen Fall nach Schnelligkeit suchen verdient nicht den absoluten und völligen Respekt für die totalen Regeln der Normalisierung, einfach weil es ein sehr kurzlebiges Dienstprogramm sein wird)

Also stimme ich in zwei Punkten zu:

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

(B.) Bei Migrationen, bei der Replikation von Datenbanken oder bei der Behebung von Notfällen handelt es sich um ein GROSSARTIGES WERKZEUG, das zum Glück vorhanden war, als ich auf die Suche ging, ob es vorhanden war.

3
David L