Gute Erklärung des Kaskadenverhaltens (ON DELETE / UPDATE)


98

Ich entwerfe nicht jeden Tag Schemata, aber wenn ich das tue, versuche ich, Kaskadenaktualisierungen / -löschungen korrekt einzurichten, um die Verwaltung zu vereinfachen. Ich verstehe, wie Kaskaden funktionieren, aber ich kann mich nie erinnern, welcher Tisch welcher ist.

Wenn ich zum Beispiel zwei Tabellen habe - Parentund Child- mit einem Fremdschlüssel auf Childdiesen Referenzen Parentund ON DELETE CASCADEwelche Datensätze lösen eine Kaskade aus und welche Datensätze werden von der Kaskade gelöscht? Meine erste Vermutung wäre, dass die ChildDatensätze gelöscht werden, wenn ParentDatensätze gelöscht werden, da ChildDatensätze von Datensätzen abhängen Parent, aber das ON DELETEist mehrdeutig; es könnte das bedeuten löschen ParentDatensatz , wenn der ChildDatensatz gelöscht wird, oder es könnte das bedeuten löschen ChildDatensatz , wenn die Parentgelöscht wird. Also was ist es?

Ich wünschte, die Syntax wäre ON PARENT DELETE, CASCADE, ON FOREIGN DELETE, CASCADEoder etwas ähnliches, um die Mehrdeutigkeit zu beseitigen. Hat jemand irgendwelche Mnemonics, um sich daran zu erinnern?

Antworten:


138

Wenn Sie die mögen Parentund ChildBegriffe und Sie fühlen sich leicht daran erinnert zu werden, können Sie die Übersetzung gerne von ON DELETE CASCADEzuLeave No Orphans!

Das heißt, wenn eine ParentZeile gelöscht (getötet) wird, sollte keine verwaiste Zeile in der ChildTabelle am Leben bleiben . Alle Kinder der übergeordneten Zeile werden ebenfalls getötet (gelöscht). Wenn eines dieser Kinder Enkelkinder hat (in einer anderen Tabelle durch einen anderen Fremdschlüssel) und dort ON DELETE CASCADEdefiniert ist, sollten diese ebenfalls getötet werden (und alle Nachkommen, sofern ein Kaskadeneffekt definiert ist).

Die FOREIGN KEYEinschränkung selbst könnte auch als Allow No Orphans!(an erster Stelle) beschrieben werden. Nein Childsollte in der untergeordneten Tabelle jemals erlaubt (geschrieben) werden, wenn es kein Parent(eine Zeile in der übergeordneten Tabelle) hat.

Aus Konsistenzgründen ON DELETE RESTRICTkann das in das (weniger aggressive) übersetzt werden. You Can't Kill Parents!Nur kinderlose Zeilen können getötet (gelöscht) werden.


3
Ich habe das Gefühl, dass in der Analogie noch etwas fehlt. Kann ein Kind nicht mehr als einen Elternteil haben? Wird in diesem Fall der Tod eines Elternteils das Kind zu einer Waise machen?
12.

7
@ Jus12 Nein, Fremdschlüsseleinschränkungen funktionieren nur mit einem übergeordneten Element. Diesbezüglich ist es keine gute Analogie.
ypercubeᵀᴹ

1
@ypercube: Ist das nicht erlaubt? Order(custID, itemID, orderID)Dabei custIDbezieht sich auf einen Primärschlüssel in der CustomersTabelle und itemIDauf einen Primärschlüssel in der ItemsTabelle. Werden nicht Orderzwei Eltern haben?
12.

4
@ Jus12 Das ist natürlich erlaubt aber es wären 2 Fremdschlüsselbeschränkungen. Dann hätte jedes Kind (Bestellung) ein Elternteil (Kunde) und ein Elternteil (Artikel). Das Verhalten der 2 FKs kann sich jedoch unterscheiden. (So ​​könnte es zum Beispiel sein, dass das Töten von Kunden alle ihre (Befehle) Kinder tötet, das Töten von Gegenständen jedoch nicht deren Befehle.)
ypercubeᵀᴹ

1
Die übergeordnete Analogie kann immer noch funktionieren, wenn wir nicht "verwaist" sagen. Wenn sich in einem Kindereintrag zwei Verweise auf zwei separate Eltern befinden, kann dies immer noch als Kind eines geschiedenen Paares angesehen werden. Einschränken: "Ich werde nicht zulassen, dass du meine Mutter tötest" Cascade: "Wenn du meinen Vater tötest, werde ich auch sterben"
Christopher McGowan

31

Wenn ich beispielsweise zwei Tabellen habe - Parent und Child -, in denen Child-Datensätze zu Parent-Datensätzen gehören, für welche Tabelle ist ON DELETE CASCADE erforderlich?

ON DELETE CASCADE ist eine optionale Klausel in einer Fremdschlüsseldeklaration. So geht es mit der Fremdschlüsseldeklaration. (Bedeutet, in der "Kind" -Tabelle.)

... kann das Löschen des übergeordneten Datensatzes bedeuten, wenn der untergeordnete Datensatz gelöscht wird, oder das Löschen des untergeordneten Datensatzes, wenn der übergeordnete Datensatz gelöscht wird. Also was ist es?

Eine Möglichkeit, eine Fremdschlüsseldeklaration zu interpretieren, ist "Alle gültigen Werte für diese Spalte stammen aus 'that_column' in 'that_table'." Wenn Sie eine Zeile in der Tabelle "child" löschen, kümmert sich niemand darum. Die Datenintegrität wird nicht beeinträchtigt.

Wenn Sie eine Zeile aus der "übergeordneten" Tabelle - aus "that_table" - löschen, entfernen Sie einen gültigen Wert aus den möglichen Werten für die "untergeordnete" Tabelle. Um die Datenintegrität zu erhalten, müssen Sie tun etwas zum „Kind“ Tabelle. Das Kaskadieren von Löschvorgängen ist eine Sache, die Sie tun können.


2

SQL: 2011 Spec

Es gibt fünf Optionen für ON DELETE, und ON UPDATEdas kann auf die zutreffen FOREIGN KEY. Diese werden <referential actions>direkt aus der SQL: 2011-Spezifikation aufgerufen

  • ON DELETE CASCADE: Wenn eine Zeile der referenzierten Tabelle gelöscht wird, werden alle übereinstimmenden Zeilen in der referenzierenden Tabelle gelöscht.
  • ON DELETE SET NULL: Wenn eine Zeile der referenzierten Tabelle gelöscht wird, müssen alle referenzierenden Spalten in allen übereinstimmenden Zeilen der referenzierenden Tabelle auf null gesetzt werden.
  • ON DELETE SET DEFAULT: Wenn eine Zeile der referenzierten Tabelle gelöscht wird, werden alle referenzierenden Spalten in allen übereinstimmenden Zeilen der referenzierenden Tabelle auf den Standardwert der Spalte gesetzt.
  • ON DELETE RESTRICT: Es ist verboten, eine Zeile der referenzierten Tabelle zu löschen, wenn diese Zeile übereinstimmende Zeilen in der referenzierenden Tabelle enthält.
  • ON DELETE NO ACTION (Standardeinstellung) : Es gibt keine referenzielle Löschaktion. Die referenzielle Einschränkung gibt nur eine Einschränkungsüberprüfung an.

Der Fremdschlüssel stellt die abhängige Beziehung her. Das <referential action>bestimmt, was passiert, wenn die Beziehung aufgelöst wird.

Beispiel / Metapher / Erklärung

In diesem Beispiel werden wir das gemeinsame Modell von Gesellschaft und Wirtschaft akzeptieren: Jedes businessUnternehmen unterhält eine Beziehung zu den bourgeoisiedurch a fatcat_owner.

CREATE TABLE bourgeoisie(
  fatcat_owner varchar(100) PRIMARY KEY
);
INSERT INTO bourgeoisie(fatcat_owner) VALUES
  ( 'Koch Brothers' );

CREATE TABLE business (
  name         varchar(100),
  fatcat_owner varchar(100) REFERENCES bourgeoisie
);
INSERT INTO business(name, fatcat_owner)
  VALUES ('Georgia-Pacific', 'Koch Brothers');

Wenn alle businesses von direkt betroffen sind bourgeoisiedurch ihre fatcat_ownerdann was tun Sie , nachdem die Arbeiterrevolution , als dass Sie die Säuberung fatcat_owners und haben eine klassenlose Gesellschaft?

-- Viva la revolución 
BEGIN;
  DELETE FROM bourgeoisie;
END;

Sie haben hier ein paar Möglichkeiten,

  • Stoppen Sie die Revolution. Im SQL-Sprachgebrauch RESTRICT. Einige Leute glauben, dass dies das geringere Übel ist, aber sie irren sich normalerweise.
  • Lass es weitergehen. Wenn ja, wenn die Revolution passiert, gibt Ihnen SQL vier Möglichkeiten,

    • SET NULL-- frei lassen. Wer weiß, vielleicht wird der Kapitalismus wiederhergestellt bourgeoisie, und Oligarchen füllen die Rolle der fatcat_owners. Wichtiger Hinweis, die Spalte muss NULLABLE(nicht NOT NULL) sein, sonst kann das nie passieren.
    • SET DEFAULT- Vielleicht hattest du einen DEFAULT, der das erledigt hat? A DEFAULTkann eine Funktion aufrufen. Vielleicht ist Ihr Schema bereits revolutionär.
    • CASCADE- Es gibt keine Schadensbegrenzung. Wenn das bourgeoisiegeht, geht das auch business. Wenn ein Unternehmen muss eine hat fatcat_pig, dann manchmal ist es sinnvoller , die Daten zu verlieren lieber als ein nicht-Geschäft in einer businessTabelle.
    • NO ACTION- Dies ist im Wesentlichen eine Methode, um die Überprüfung zu verzögern. In MySQL ist dies nicht anders als RESTRICTin PostgreSQL

      -- Not a real revolution.
      -- requires constraint be DEFERRABLE INITIALLY DEFERRED
      BEGIN;
        SET CONSTRAINTS ALL DEFERRED;
        DELETE FROM bourgeoisie;
        INSERT INTO bourgeoisie VALUES ( 'Putin' );
        UPDATE business SET fatcat_pig = 'Putin';
      END;

      In einem solchen System wird die Einschränkung erst validiert, bevor die Transaktion festgeschrieben wird. Dies kann dazu führen, dass die Revolution abgebrochen wird, Sie können sich jedoch in der Transaktion erholen - für einen gewissen Grad an "Wiederherstellung".


Bedeutet referencedTabelle übergeordnete Tabelle und referencingTabelle untergeordnete Tabelle?
sg552

@ sg552 Ja, du hast es richtig verstanden.
informatik01

0

Eine einfache Gedächtnisstütze wäre

ON DELETE des übergeordneten CASCADE [durch Löschen] hier

Hier erfahren Sie, welche Löschvorgänge (Löschvorgänge des übergeordneten Elements) kaskadiert werden, wohin die Anweisung ON DELETE CASCADE (für das untergeordnete Element ) wechselt und was gelöscht wird (für das untergeordnete Element ).


-3

Nun, vielleicht können wir die Syntax rationalisieren. Nehmen wir ein Python-Beispiel:

class Parent(self):
    # define parent's fields

class Child(self):    
    # define child's fields
    parent_pk_is_childs_foreign_key = models.ForeignKey(Parent, on_delete=models.CASCADE)

Was in dieser Zeile steht, ist on_delete des übergeordneten Elements (was in der Anweisung versehentlich erwähnt wird). Bitte kaskadieren Sie die Löschung auf das untergeordnete Element. Aus diesem Grund wird die CASCADE-Anweisung auf untergeordneter Ebene definiert und markiert diejenigen untergeordneten Elemente, die gelöscht werden müssen

Zum Beispiel, wenn Sie eine andere Klasse hatten

class GrownUpChild(self):    
        # define grown up child's fields
        parent_pk_is_childs_foreign_key = models.ForeignKey(Parent, on_delete=models.DO_NOTHING)

Diese Struktur würde deutlich machen, welches der Kinder entfernt werden muss (Child) und welches bleiben soll (GrownUpChild), obwohl es verwaist ist

[Bearbeiten: In Anbetracht des Diskussionskontexts, insbesondere in Fällen von on_delete = models.CASCADE usw.] ist es häufig erwünscht, Kinder eines gelöschten Elternteils zu lassen, und zwar aus Gründen der Überwachung und Berichterstattung sowie aus Gründen der Wiederherstellung aus Versehen Streichungen. [Natürlich wird Software auf Unternehmensebene um dieses Verhalten herum entwickelt und gelöschte Datensätze als gelöscht = 1 markieren, anstatt sie tatsächlich zu löschen, und sie werden auch nicht in Abfragen für das Front-End enthalten sein, abzüglich einiger speziell gestalteter Berichte. Außerdem werden die gelöschten == 1-Datensätze aus der Datenbank entfernt, was normalerweise vom Benutzeroberflächenadministrator ausgeführt wird, wobei häufig eine Beteiligung des Datenbankadministrators vermieden wird.]


1
"Tatsächlich ist es häufig ein erwünschtes Verhalten, Kinder eines gelöschten Elternteils zu lassen, und zwar aus Gründen der Überwachung und Berichterstattung sowie zur Wiederherstellung versehentlicher Löschungen" - das wäre in einer (vernünftigen) Datenbank katastrophal.
Dezso

@dezso danke für deine Eingabe. Genau das tun jedoch mehrere CRM-Systeme auf Unternehmensebene.
George Mogilevsky

TBH, das macht es nicht sinnvoller. Ich habe einmal den Auftrag bekommen, die Scheiße zu reparieren, die aus einem solchen Ansatz resultiert - keine Freude, außer dem Gehaltsscheck.
Dezso

Sie klingen wie ein versierter Datenbankadministrator :) Ich kann Ihren Standpunkt vollkommen verstehen. Die oben erwähnte Software, die dies tut, hat tatsächlich eine Funktion zum manuellen Entfernen der gelöschten = 1, sodass es dem Administrator der App überlassen ist, diesen Anruf zu tätigen. Normalerweise ist der Datenbankadministrator nicht einmal an der Pflege dieses Aspekts beteiligt. Außerdem basiert die gesamte Datenbankklasse der Software auf dem Konzept, sodass bei Rohoperationen immer nach gelöschten Markierungen gesucht wird
George Mogilevsky,

Ja, das ist ein bekanntes und vernünftiges Muster - aber dann sollten Sie möglicherweise den obigen Wortlaut ändern, um dies widerzuspiegeln.
Dezso
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.