Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Einschränkungen für Fremdschlüssel:Wann sollten ON UPDATE und ON DELETE verwendet werden?

Zögern Sie nicht, der Datenbank Einschränkungen aufzuerlegen. Sie werden sicher sein, eine konsistente Datenbank zu haben, und das ist einer der guten Gründe, eine Datenbank zu verwenden. Vor allem, wenn Sie mehrere Anwendungen haben, die dies anfordern (oder nur eine Anwendung, aber mit einem Direktmodus und einem Stapelmodus, die unterschiedliche Quellen verwenden).

Mit MySQL haben Sie keine erweiterten Beschränkungen wie in PostgreSQL, aber zumindest die Fremdschlüsselbeschränkungen sind ziemlich fortgeschritten.

Wir nehmen ein Beispiel, eine Firmentabelle mit einer Benutzertabelle, die Personen aus dieser Firma enthält

CREATE TABLE COMPANY (
     company_id INT NOT NULL,
     company_name VARCHAR(50),
     PRIMARY KEY (company_id)
) ENGINE=INNODB;

CREATE TABLE USER (
     user_id INT, 
     user_name VARCHAR(50), 
     company_id INT,
     INDEX company_id_idx (company_id),
     FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;

Schauen wir uns das ON UPDATE an Klausel:

  • BESCHRÄNKUNG AUF AKTUALISIERUNG :Standard :Wenn Sie versuchen, eine company_id in der Tabelle COMPANY zu aktualisieren, wird die Engine die Operation ablehnen, wenn mindestens ein USER auf diese Firma verlinkt.
  • BEIM AKTUALISIEREN KEINE AKTION :dasselbe wie RESTRICT.
  • ON UPDATE CASCADE :normalerweise der beste :Wenn Sie eine company_id in einer Zeile der Tabelle COMPANY aktualisieren, aktualisiert die Engine sie entsprechend in allen USER-Zeilen, die auf diese COMPANY verweisen (aber keine Trigger in der USER-Tabelle aktiviert, Warnung). Die Engine verfolgt die Änderungen für Sie, das ist gut.
  • BEI AKTUALISIERUNG NULL SETZEN :Wenn Sie eine company_id in einer Zeile der Tabelle COMPANY aktualisieren, setzt die Engine die zugehörigen USER company_id auf NULL (sollte im Feld USER company_id verfügbar sein). Ich kann in einem Update nichts Interessantes dazu finden, aber ich kann mich irren.

Und jetzt auf BEIM LÖSCHEN Seite:

  • EINSCHRÄNKUNG AUF LÖSCHEN :Standard :Wenn Sie versuchen, eine company_id-ID in der Tabelle COMPANY zu löschen, wird die Engine die Operation ablehnen, wenn ein USER mindestens auf diese Firma verlinkt, kann Ihr Leben retten.
  • BEIM LÖSCHEN KEINE AKTION :dasselbe wie RESTRICT
  • ON DELETE CASCADE :gefährlich :Wenn Sie eine Firmenzeile in der Tabelle FIRMA löschen, löscht die Engine auch die zugehörigen BENUTZER. Dies ist gefährlich, kann aber verwendet werden, um automatische Aufräumarbeiten an Sekundärtabellen durchzuführen (es kann also etwas sein, das Sie wollen, aber ganz sicher nicht für ein COMPANY<->USER-Beispiel)
  • BEIM LÖSCHEN NULL SETZEN :Handvoll :Wenn Sie eine COMPANY-Zeile löschen, haben die zugehörigen USERs automatisch die Beziehung zu NULL. Wenn Null Ihr Wert für Benutzer ohne Unternehmen ist, kann dies ein gutes Verhalten sein, vielleicht müssen Sie die Benutzer in Ihrer Anwendung als Autoren einiger Inhalte behalten, aber das Entfernen des Unternehmens ist kein Problem für Sie.

Normalerweise ist meine Standardeinstellung:ON DELETE RESTRICT ON UPDATE CASCADE . mit etwas ON DELETE CASCADE für Spurtabellen (Logs – nicht alle Logs –, solche Sachen) und ON DELETE SET NULL wenn die Haupttabelle ein 'einfaches Attribut' für die Tabelle ist, die den Fremdschlüssel enthält, wie eine JOB-Tabelle für die USER-Tabelle.

Bearbeiten

Es ist lange her, dass ich das geschrieben habe. Jetzt denke ich, ich sollte eine wichtige Warnung hinzufügen. MySQL hat eine große dokumentierte Einschränkung bei Kaskaden. Kaskaden feuern keine Auslöser . Wenn Sie sich also in dieser Engine zu sicher genug waren, um Trigger zu verwenden, sollten Sie Cascades Constraints vermeiden.

==> Siehe unter der letzten Änderung, es tut sich was auf dieser Domain

Und ich glaube nicht, dass das eines Tages behoben wird. Fremdschlüsseleinschränkungen werden vom InnoDb-Speicher verwaltet und Trigger werden von der MySQL-SQL-Engine verwaltet. Beide sind getrennt. Innodb ist der einzige Speicher mit Constraint-Management, vielleicht werden sie eines Tages Trigger direkt in der Speicher-Engine hinzufügen, vielleicht auch nicht.

Aber ich habe meine eigene Meinung darüber, welches Element Sie zwischen der schlechten Trigger-Implementierung und der sehr nützlichen Unterstützung für Fremdschlüssel-Einschränkungen wählen sollten. Und sobald Sie sich an die Datenbankkonsistenz gewöhnt haben, werden Sie PostgreSQL lieben.

12/2017-Aktualisierung dieser Bearbeitung über MySQL:

Wie von @IstiaqueAhmed in den Kommentaren angegeben, hat sich die Situation zu diesem Thema geändert. Folgen Sie also dem Link und prüfen Sie den wirklich aktuellen Stand (der sich in Zukunft wieder ändern kann).