Zögern Sie nicht, die Datenbank einzuschränken. Sie werden sicher eine konsistente Datenbank haben, und das ist einer der guten Gründe, eine Datenbank zu verwenden. Insbesondere, wenn mehrere Anwendungen dies anfordern (oder nur eine Anwendung, jedoch mit einem Direktmodus und einem Stapelmodus unter Verwendung verschiedener Quellen).
Mit MySQL haben Sie keine erweiterten Einschränkungen wie in postgreSQL, aber zumindest die Fremdschlüsseleinschränkungen sind ziemlich erweitert.
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 die ON UPDATE- Klausel an:
- ON UPDATE RESTRICT : Die Standardeinstellung : Wenn Sie versuchen, eine company_id in der Tabelle COMPANY zu aktualisieren, lehnt die Engine den Vorgang ab, wenn mindestens ein USER eine Verknüpfung zu dieser Firma herstellt.
- ON UPDATE KEINE AKTION : wie RESTRICT.
- ON UPDATE CASCADE : das Beste normalerweise : Wenn Sie eine company_id in einer Zeile der Tabelle COMPANY aktualisieren, aktualisiert die Engine sie entsprechend in allen USER-Zeilen, die auf dieses UNTERNEHMEN verweisen (jedoch keine Trigger in der USER-Tabelle aktiviert, Warnung). Der Motor wird die Änderungen für Sie verfolgen, es ist gut.
- ON UPDATE SET NULL : Wenn Sie eine company_id in einer Zeile der Tabelle COMPANY aktualisieren, setzt die Engine die zugehörigen USERs company_id auf NULL (sollte im Feld USER company_id verfügbar sein). Ich kann bei einem Update nichts Interessantes sehen, aber ich kann mich irren.
Und jetzt auf ON DELETE Seite:
- ON DELETE RESTRICT : Die Standardeinstellung : Wenn Sie versuchen, eine company_id-ID in der Tabelle COMPANY zu löschen, lehnt die Engine den Vorgang ab, wenn ein USER mindestens Links zu dieser Firma erstellt, was Ihr Leben retten kann.
- ON LÖSCHEN KEINE AKTION : wie RESTRICT
- ON DELETE CASCADE : gefährlich : Wenn Sie eine Unternehmenszeile in der Tabelle COMPANY löschen, löscht die Engine auch die zugehörigen USERs. Dies ist gefährlich, kann jedoch verwendet werden, um automatische Bereinigungen für sekundäre Tabellen durchzuführen (es kann also etwas sein, das Sie möchten, aber mit Sicherheit nicht für ein Beispiel eines UNTERNEHMENS <-> USER).
- ON DELETE SET NULL : Handvoll : Wenn Sie eine COMPANY-Zeile löschen, haben die zugehörigen USER automatisch die Beziehung zu NULL. Wenn Null Ihr Wert für Benutzer ohne Unternehmen ist, kann dies ein gutes Verhalten sein. Möglicherweise müssen Sie die Benutzer in Ihrer Anwendung als Autoren einiger Inhalte behalten, aber das Entfernen des Unternehmens ist für Sie kein Problem.
Normalerweise ist meine Standardeinstellung: ON DELETE RESTRICT ON UPDATE CASCADE . mit einigen ON DELETE CASCADE
für Track-Tabellen (Protokolle - nicht alle Protokolle -, solche Dinge) undON DELETE SET NULL
wenn die Master-Tabelle 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, seit ich das geschrieben habe. Jetzt denke ich, ich sollte eine wichtige Warnung hinzufügen. MySQL hat eine große dokumentierte Einschränkung mit Kaskaden. Kaskaden lösen keine Auslöser aus . Wenn Sie also zu sicher genug sind, Trigger zu verwenden, sollten Sie Kaskadenbeschränkungen vermeiden.
MySQL-Trigger werden nur für Änderungen aktiviert, die von SQL-Anweisungen an Tabellen vorgenommen wurden. Sie werden weder für Änderungen in Ansichten noch für Änderungen an Tabellen aktiviert, die von APIs vorgenommen wurden, die keine SQL-Anweisungen an den MySQL Server übertragen
==> Siehe unten, die letzte Änderung, die Dinge bewegen sich auf dieser Domain
Trigger werden nicht durch Fremdschlüsselaktionen aktiviert.
Und ich glaube nicht, dass dies eines Tages behoben wird. Fremdschlüsseleinschränkungen werden vom InnoDb-Speicher und Trigger von der MySQL SQL-Engine verwaltet. Beide sind getrennt. Innodb ist der einzige Speicher mit Constraint-Management. Vielleicht werden eines Tages Trigger direkt in die Speicher-Engine eingefügt, vielleicht auch nicht.
Ich bin jedoch der Meinung, welches Element Sie zwischen der schlechten Triggerimplementierung und der sehr nützlichen Unterstützung für Fremdschlüsseleinschrä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 in diesem Bereich geändert. Folgen Sie also dem Link und überprüfen Sie die aktuelle Situation (die sich in Zukunft möglicherweise wieder ändern wird).
ON DELETE CASCADE : dangerous
- Mit einer Prise Salz einnehmen.SET NULL
in einemON UPDATE
: ein Unternehmen , das Aktualisieren einer Ablösung der Gesellschaft repräsentiert> Benutzer Beziehung. Beispiel: Wenn ein Unternehmen seinen Geschäftstyp ändert, sind die vorherigen Benutzer möglicherweise nicht mehr mit diesem Geschäft verbunden. DaherNULL
ist dies für diesen Index möglicherweise vorzuziehen.This includes changes to base tables that underlie updatable views
anstelle dessen, was Sie eingefügt haben, dhThey do not activate for changes in views
CASCADE DELETE
ist dies im Allgemeinen auch in Ordnung, sogar bevorzugt. Ich halte es nicht für besonders gefährlich.Ergänzung zur @ MarkR-Antwort - Eine Sache, die zu beachten ist, ist, dass viele PHP-Frameworks mit ORMs das erweiterte DB-Setup (Fremdschlüssel, kaskadierendes Löschen, eindeutige Einschränkungen) nicht erkennen oder verwenden. Dies kann zu unerwartetem Verhalten führen.
Wenn Sie beispielsweise einen Datensatz mit ORM
DELETE CASCADE
löschen und Datensätze in verwandten Tabellen löschen, führt der Versuch von ORM, diese verwandten Datensätze (häufig automatisch) zu löschen, zu einem Fehler.quelle
Sie müssen dies im Kontext der Anwendung berücksichtigen. Im Allgemeinen sollten Sie eine Anwendung entwerfen, keine Datenbank (die Datenbank ist einfach Teil der Anwendung).
Überlegen Sie, wie Ihre Anwendung auf verschiedene Fälle reagieren soll.
Die Standardaktion besteht darin, den Vorgang einzuschränken (dh nicht zuzulassen), was normalerweise gewünscht wird, da er dumme Programmierfehler verhindert. Bei DELETE kann CASCADE jedoch auch nützlich sein. Es hängt wirklich von Ihrer Anwendung ab und davon, wie Sie bestimmte Objekte löschen möchten.
Persönlich würde ich InnoDB verwenden, weil es Ihre Daten nicht in den Papierkorb wirft (siehe MyISAM), anstatt weil es FK-Einschränkungen gibt.
quelle