Unterschied zwischen On Delete Cascade und On Update Cascade in mysql


45

Ich habe zwei Tabellen in MySQL database- parent, child. Ich versuche, meiner untergeordneten Tabelle Fremdschlüsselverweise hinzuzufügen, die auf der übergeordneten Tabelle basieren. Gibt es einen signifikanten Unterschied zwischen ON UPDATE CASCADEund?ON DELETE CASCADE

Mein Elterntisch

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

Meine Frage ist: Was ist der Unterschied zwischen den folgenden SQL-Abfragen.

  1. ON DELETE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON DELETE CASCADE
    ) ENGINE=INNODB;
  2. ON UPDATE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON UPDATE CASCADE
    ) ENGINE=INNODB;
  3. ON UPDATE CASCADE ON DELETE CASCADE

    CREATE TABLE child (
            id INT, 
            parent_id INT,
            INDEX par_ind (parent_id),
            FOREIGN KEY (parent_id) 
                REFERENCES parent(id)
                ON UPDATE CASCADE ON DELETE CASCADE
        ) ENGINE=INNODB;

Gibt es irgendwelche Fehler in den Abfragen? Was bedeuten diese Abfragen (1,2 & 3)? Sind sie gleich ???


1
ps <nitpick> Der Vollständigkeit halber sprechen Sie hier von DDL- Anweisungen (Data Definition Language) und nicht von Abfragen. Eine Abfrage wird im Allgemeinen als DML (Datenbearbeitungssprache SELECT, INSERT, UPDATE, DELETE) betrachtet. </ Nitpick>
Vérace

Noch ein ps der Vollständigkeit halber habe ich mich gefragt, was der Standard war. Also habe ich ein Kind ohne beim Update oder beim Löschen erstellt. Was dann passiert, ist, dass Sie einen Elternteil, der ein abhängiges Kind hat, weder aktualisieren noch löschen können. Das macht durchaus Sinn, aber MySQL ist nicht immer ein Modell dieser besonderen Eigenschaft :-)
Vérace

Antworten:


64

Ein sehr guter Thread zu diesem Thema ist hier und auch hier zu finden . Die endgültige Anleitung für MySQL ist natürlich die Dokumentation, die hier zu finden ist .

Im SQL 2003-Standard gibt es 5 verschiedene Referenzaktionen:

  1. KASKADE
  2. BESCHRÄNKEN
  3. KEINE AKTION
  4. SET NULL
  5. STANDARD EINSTELLEN

Um die Frage zu beantworten:

  1. KASKADE

    • ON DELETE CASCADEbedeutet, dass beim Löschen des übergeordneten Datensatzes auch alle untergeordneten Datensätze gelöscht werden. Dies ist meiner Meinung nach keine gute Idee. Sie sollten alle Daten, die sich jemals in einer Datenbank befunden haben, im Auge behalten, obwohl dies mit TRIGGERs möglich ist. (Siehe jedoch Vorbehalt in den Kommentaren unten).

    • ON UPDATE CASCADEbedeutet, dass sich der untergeordnete Wert ändert, wenn der übergeordnete Primärschlüssel geändert wird, um dies widerzuspiegeln. Wieder meiner Meinung nach keine gute Idee. Wenn Sie PRIMARY KEYs regelmäßig (oder sogar überhaupt!) Ändern , stimmt etwas nicht mit Ihrem Design. Siehe auch hier Kommentare.

    • ON UPDATE CASCADE ON DELETE CASCADEbedeutet, dass, wenn Sie UPDATE ODER DELETE das übergeordnete Element auswählen, die Änderung an das untergeordnete Element weitergeleitet wird. Dies entspricht ANDden Ergebnissen der ersten beiden Aussagen.

  2. BESCHRÄNKEN

    • RESTRICTbedeutet, dass jeder Versuch, das übergeordnete Element zu löschen und / oder zu aktualisieren, fehlschlägt und einen Fehler auslöst. Dies ist das Standardverhalten für den Fall, dass eine referenzielle Aktion nicht explizit angegeben wird.

      Für ein ON DELETEoder ON UPDATEdas nicht angegeben ist, ist die Standardaktion immer RESTRICT`.

  3. KEINE AKTION

    • NO ACTION: Aus dem Handbuch . Ein Schlüsselwort aus Standard-SQL. In MySQL entspricht RESTRICT. Der MySQL Server lehnt den Lösch- oder Aktualisierungsvorgang für die übergeordnete Tabelle ab, wenn die referenzierte Tabelle einen zugehörigen Fremdschlüsselwert enthält. Einige Datenbanksysteme haben verzögerte Prüfungen und es NO ACTIONhandelt sich um eine verzögerte Prüfung. In MySQL werden Fremdschlüsseleinschränkungen sofort überprüft, NO ACTIONgenauso wie in RESTRICT.
  4. SET NULL

    • SET NULL- wieder aus dem Handbuch. Löschen oder aktualisieren Sie die Zeile aus der übergeordneten Tabelle und setzen Sie die Fremdschlüsselspalte (n) in der untergeordneten Tabelle auf NULL. Dies ist meiner Meinung nach nicht die beste Idee, vor allem, weil es keine Möglichkeit zum "Zeitreisen" gibt - dh Rückblick auf die untergeordneten Tabellen und Zuordnen von Datensätzen zu NULLs zum entsprechenden übergeordneten Datensatz - CASCADEoder um TRIGGERProtokollierungstabellen zum Verfolgen mit s zu füllen Änderungen (siehe aber Kommentare).
  5. STANDARD EINSTELLEN

    • SET DEFAULT. Ein weiterer (möglicherweise sehr nützlicher) Teil des SQL-Standards, den MySQL nicht implementiert hat! Ermöglicht dem Entwickler, einen Wert anzugeben, auf den die Fremdschlüsselspalte (n) bei einem UPDATE oder einem DELETE festgelegt werden sollen. InnoDB und NDB lehnen Tabellendefinitionen mit einer SET DEFAULTKlausel ab.

Wie oben erwähnt, sollten Sie sich hier ein wenig mit der Dokumentation befassen .


8
Ich mag Ihre vollständige Antwort, aber ich bin mit dieser Aussage nicht einverstanden. "Sie sollten alle Daten, die sich jemals in einer Datenbank befunden haben, im Auge behalten" - dies hängt wirklich vom Design und dem Zweck der Datenbank ab. Beispiel: Eine Rezeptdefinition (ich spreche nicht von Essen - eher von Systemkonfigurationen), bei der die Rezeptdefinition gelöscht wird, macht es keinen Sinn, die zugehörigen untergeordneten Elemente dieses Rezepts beizubehalten. Dadurch wird die Datenbank ohne Grund aufgebläht. Auch Arbeitstische für Maschinensysteme - ich brauche die Daten nicht mehr; verarbeiten und loswerden. Davon abgesehen ist Ihre Antwort fantastisch.
StixO

2
ähnlich wie @StixO Ich mag diese Antwort meistens, aber ich muss nicht zustimmen, Primärschlüssel zu ändern. Es gibt definitiv Entwürfe, bei denen dies eine schlechte Idee wäre, aber wenn Sie in eine verteilte Datenbank gelangen, kann es sehr wünschenswert sein, dass Primärschlüssel frei zugewiesen werden können, ohne die Identität eines Datensatzes zu verlieren.
Garet Claborn

"Das ist meiner Meinung nach keine gute Idee. Sie sollten alle Daten, die jemals in einer Datenbank waren, im Auge behalten." - Ich verstehe Ihren Standpunkt nicht. Wenn Sie "on delete" kaskadieren, haben Sie bereits entschieden, dass Sie etwas löschen müssen. Wenn Sie sich entscheiden, niemals etwas zu löschen, wird nichts kaskadieren. Der Vorteil ist jedoch, dass Sie in Ihrer Anwendung sicher sein können, dass beim Suchen nach einem Datensatz mit einer fremden ID dieser vorhanden ist und keine verwaisten Zeilen Ihre Datenbank aufblähen, falls Sie sich zum Löschen entschließen etwas.
Jeff Ryan

Die Logik hier ist an einigen Stellen ziemlich fehlerhaft, insbesondere in unserer neuen GDPR-Welt. Ich stimme der Vorstellung zu, dass eine Änderung des Primärschlüssels ein Zeichen für einen Fehler sein könnte.
Chuck Le Butt

Wenn Sie PRIMARY KEYs regelmäßig (oder gar nicht) ändern, stimmt etwas nicht mit Ihrem Design. Meinen Sie, dass ON UPDATE CASCADE den Wert des Schlüssels oder den Namen des Schlüssels ändert?
Billal Begueradj

8

Diese beiden Aktionen müssen ausgeführt werden, wenn der Datensatz, auf den verwiesen wird, in der übergeordneten Tabelle seine ID ändert und wenn er gelöscht wird.

Wenn Sie ausführen:

UPDATE parent SET id = -1 WHERE id = 1;

Und es gibt mindestens einen Datensatz auf childmit parent_id = 1, 1) wird fehlschlagen; In den Fällen 2) und 3) werden alle Datensätze mit parent_id = 1 auf parent_id = -1 aktualisiert.

Wenn Sie ausführen:

DELETE FROM parent WHERE id = 1;

Und es gibt mindestens einen Datensatz auf childmit parent_id = 1, 2) wird fehlschlagen; In den Fällen 1) und 3) werden alle Datensätze mit parent_id = 1gelöscht.

3) ist syntaktisch korrekt.

Die vollständige Dokumentation finden Sie im Handbuch .


6

Ich habe nicht genug Ansehen, um die vorherigen Antworten zu kommentieren. Also dachte ich, ich würde etwas näher darauf eingehen.

1) ON DELETE CASCADE bedeutet, dass beim Löschen des übergeordneten Datensatzes auch alle referenzierenden untergeordneten Datensätze gelöscht werden. ON UPDATE ist standardmäßig RESTRICT, was bedeutet, dass das UPDATE im übergeordneten Datensatz fehlschlägt.

2) Die Standardeinstellung für die Aktion ON DELETE ist RESTRICT. Dies bedeutet, dass das Löschen im übergeordneten Datensatz fehlschlägt. ON UPDATE CASCADE aktualisiert alle referenzierenden untergeordneten Datensätze, wenn der übergeordnete Datensatz aktualisiert wird.

3) Siehe die CASCADE-Aktionen in 1) und 2) oben.

Übergeordnete Datensatz-IDs als Fremdschlüssel (in untergeordneten Tabellen) verwenden - Erfahrungsgemäß werden a) automatisch generierte Folgenummern NICHT als Fremdschlüssel verwendet. Verwenden Sie stattdessen einen anderen eindeutigen übergeordneten Schlüssel. b) Wenn die IDs GUIDs sind, ist es in Ordnung, sie als Fremdschlüssel zu verwenden. Sie werden die Weisheit in diesem Vorschlag sehen, wenn Sie die Datensätze exportieren und importieren oder in eine andere Datenbank kopieren. Es ist zu umständlich, mit automatisch generierten Sequenznummern während der Datenmigration umzugehen, wenn sie als Fremdschlüssel referenziert werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.