Fremdschlüssel sind ein wesentlicher Bestandteil beim Erstellen einer Beziehung in relationalen Datenbanken. Hier ist der Grund und wie man sie erstellt.
Wir haben also festgestellt, dass ein Primärschlüssel eine eindeutige Kennung für die Tabelle bereitstellt. Aber Primärschlüssel sind nicht der einzige "Schlüssel"-Typ. Unsere Datenbank kann auch Fremdschlüssel enthalten.
Was ist ein Fremdschlüssel?
Ein Fremdschlüssel ist eine Spalte (oder Sammlung von Spalten) in einer Tabelle, die eine Zeile einer anderen Tabelle eindeutig identifiziert. Dies definiert eine Beziehung zwischen den beiden Tabellen.
Ein Fremdschlüssel ermöglicht es Ihnen, tabellenübergreifende Querverweise auf verwandte Daten zu erstellen. Dies ist praktisch, wenn eine Spalte Daten enthält, die in einer anderen Tabelle dargestellt werden.
Beispiel
Hier ist ein Diagramm unseres FruitShop Datenbank, die die Beziehung zwischen der Frucht zeigt Tabelle und die Einheiten Tisch.
Die schwarze Linie, die die beiden Tabellen verbindet, zeigt einen Fremdschlüssel an. Die UnitId Feld auf Obst table ist ein Fremdschlüssel zur UnitId Feld auf den Einheiten Tisch. Daher der Wert, den wir in Fruit.UnitId einfügen muss einem Wert in Units.UnitId entsprechen . Dies aktiviert die Fruit.UnitId um auf die Daten in den anderen Spalten für diesen Datensatz zu verweisen (d. h. den Datensatz mit der entsprechenden UnitId ). ).
Die Daten
Wenn also unser Obst Tabelle enthält einen Datensatz wie diesen:
FruitId | Fruchtname | Inventar | Einheiten-ID | Eingabedatum | Aktualisierungsdatum |
---|---|---|---|---|---|
1 | Apfel | 10 | 3 | 2012-11-27 12:42:10 | 2012-11-27 12:42:10 |
Und unsere Einheiten Tabelle enthält die folgenden Datensätze:
Einheiten-ID | Einheitenname | Eingabedatum | Aktualisierungsdatum |
---|---|---|---|
1 | Stück | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
2 | Haufen | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
3 | Kilogramm | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
4 | Behälter | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
5 | Pfund | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
6 | Unze | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
Sie können sehen, dass die
Fruit.UnitId
Feld enthält eine 3
. Sehen Sie sich nun die
Units
an Tabelle für den Datensatz, der eine 3
enthält in der
UnitId
Feld. Sie können sehen, dass dieser Datensatz
Kilogramm
darstellt . Daher wissen wir jetzt, dass Äpfel in Kilogramm gemessen werden.
Das Gute an der Einrichtung der Datenbank auf diese Weise ist, dass wir „Kilogramm“ nicht für jeden Datensatz wiederholen müssen, der diese Einheit verwendet. Das Reduzieren von Duplikaten ist ein wesentlicher Vorteil relationaler Datenbankverwaltungssysteme.
So viele Datensätze in Fruit sehen Tabelle denselben Einheitsnamen haben (z. B. „Kilogramm“, „Container“, „Bündel“ usw.), sollten wir sorgfältig überlegen, bevor wir Duplikate zu unserer Datenbank hinzufügen. Ohne eine Fremdschlüsselbeziehung zu verwenden, könnten wir die Unit-Namen einfach direkt in die Fruit schreiben Tabelle (und nennen Sie die Spalte vielleicht "Unit", "UnitType" oder "UnitName"). Dann würden wir am Ende viele Datensätze haben, die denselben Wert für die Spalte mit dem Einheitennamen teilen. Wir würden "Kilogram" immer wieder gegen viele Rekorde wiederholen sehen. Wir würden auch "Bündel" wiederholt sehen und jeden anderen beliebten Einheitentyp.
Obwohl es nicht unbedingt "falsch" ist, dies zu tun, ist es im Allgemeinen effizienter, einen Datensatz für jeden dieser Einheitennamen in einer separaten Tabelle zu speichern und dann diese Tabelle über die UnitId zu referenzieren Säule. Dies ist effizienter, als diese Unit-Namen immer und immer wieder für jeden Datensatz zu wiederholen, der in Fruits erstellt wird Tisch. Es macht es auch einfacher, wenn wir uns jemals entscheiden, einen Einheitennamen zu ändern (z. B. „Kilogramm“ in „Kilo“ ändern). Wenn wir einen Unit-Namen aktualisieren, würde das Fruit nicht beeinflussen Tabelle, da die UnitId wird gleich bleiben. Außerdem hilft es auch zu verhindern, dass inkonsistente Daten in unserer Datenbank auftauchen.
Fremdschlüsselbeschränkung
Eine Fremdschlüsseleinschränkung ist ein Datenbankobjekt, das dabei hilft, Ihre Fremdschlüsseldaten konsistent zu halten. Sie erstellen eine Fremdschlüsseleinschränkung, um die referenzielle Integrität aufrechtzuerhalten. Indem Sie eine Fremdschlüsselbeschränkung erstellen, weisen Sie MySQL an, bestimmte Regeln für die Daten durchzusetzen. Wenn Daten eingefügt, gelöscht oder aktualisiert werden, prüft MySQL, ob sie dem Fremdschlüssel entsprechen, den Sie zwischen den Tabellen erstellt haben. Wenn nicht, verhindert es, dass die Daten geschrieben/überschrieben/gelöscht werden, wodurch die referenzielle Integrität aufrechterhalten wird.
Wenn beispielsweise ein Benutzer versucht, einen UnitId-Wert in Fruit.UnitId einzugeben Spalte, aber es gibt keinen entsprechenden Datensatz in der Units.UnitId -Spalte, dann hindert MySQL den Benutzer daran, diesen Wert einzugeben.
Als wir unsere beiden Tabellen erstellten, fügten wir der Fruit eine Fremdschlüsseleinschränkung hinzu Tisch. Hier ist der Code, den wir verwendet haben, um die Einschränkung zu erstellen:
CONSTRAINT fkFruitUnits FOREIGN KEY (UnitId) REFERENCES Units (UnitId) ON DELETE RESTRICT ON UPDATE CASCADE
Wenn Sie die Knoten im linken SCHEMAS erweitern können Sie den von uns erstellten Fremdschlüssel (sowie die Primärschlüssel) sehen:
Wenn Sie versuchen, Daten einzufügen, die nicht der Fremdschlüsselbeschränkung entsprechen, sollten Sie eine Fehlermeldung erhalten.
Wenn ich zum Beispiel versuche, einen Datensatz in die Datei Fruit einzufügen Tabelle mit einer UnitId Wert, der nicht in den Units existiert Tabelle erhalte ich die folgende Fehlermeldung:
Dies geschieht, weil ich versuche, einen Wert von 5
einzufügen in die
UnitId
-Spalte, wenn in
Units.UnitId
kein entsprechender Wert vorhanden ist Feld.
Damit dies gelingt, müsste ich sicherstellen, dass es einen Eintrag in den
Units
gibt Tabelle mit einer
UnitId
von 5
.
Fremdschlüssel funktioniert nicht?
Es kann gelegentlich vorkommen, dass ein Fremdschlüssel nicht zu funktionieren scheint. Beispielsweise können Sie erfolgreich Daten in eine Tabelle einfügen, obwohl es einen Fremdschlüssel gibt, der das Einfügen dieser Daten verhindern sollte.
Es gibt ein paar Dinge, die Sie in dieser Situation überprüfen können.
- Stellen Sie sicher, dass Sie
ON DELETE
angehängt haben undON UPDATE
Klauseln in Ihrem Code. Beispiel:ON DELETE RESTRICT ON UPDATE CASCADE
. Sehen Sie sich unser CREATE TABLE-Beispiel an, wann dieser Code platziert werden soll. - Stellen Sie sicher, dass die Tabelle InnoDB ist . Sie können dies tun, indem Sie
ENGINE=InnoDB
hinzufügen bis zum Ende IhresCREATE TABLE
-Anweisung (siehe mein Beispiel aus der Zeit, als wir unsere Tabellen erstellt haben). Manche Engines (wie MyISAM ) unterstützen keine Fremdschlüsseleinschränkungen, geben jedoch keine Warnung darüber aus, wenn Sie versuchen, Ihre Fremdschlüsseleinschränkung zu erstellen. Wenn Ihre Standard-Engine nicht InnoDB ist dann werden Ihre Fremdschlüssel wahrscheinlich nicht unterstützt. - Stellen Sie sicher, dass MySQL tatsächlich Fremdschlüssel prüft. Sie können dies tun, indem Sie den folgenden Code ausführen:
SET FOREIGN_KEY_CHECKS=1
.
Fremdschlüsselprüfung deaktivieren
Es kann vorkommen, dass Fremdschlüsselbeschränkungen unnötig restriktiv werden – bis zu dem Punkt, an dem sie Ihre Bemühungen beim Laden von Daten ernsthaft behindern. Zum Beispiel, wenn Sie gerade eine Datenbank erstellt haben und die Anfangsdaten laden müssen. Oder wenn Sie eine Reihe von Tabellen löschen und die Daten neu laden müssen.
Wenn Sie die Daten nicht in der richtigen Reihenfolge laden, erhalten Sie wahrscheinlich weiterhin Fremdschlüsselfehler, weil die Daten in der falschen Reihenfolge geladen werden (d. h. Sie versuchen, die untergeordneten Tabellen zu laden, bevor die übergeordneten Tabellen ihre Daten geladen).
Dies ist nicht nur ein Problem beim Laden die Daten. Dieses Problem kann auch beim Erstellen der Datenbank auftreten. Wenn Sie die Tabellen nicht in der richtigen Reihenfolge erstellen, können aufgrund von Fremdschlüsseleinschränkungen Fehler auftreten.
Wenn Sie die richtige Eltern-Kind-Reihenfolge nicht kennen, kann es möglicherweise viel Zeit und Mühe kosten, die richtige Reihenfolge zum Erstellen der Datenbank oder zum Laden der Daten festzulegen. In solchen Fällen ist es vielleicht besser, MySQL vorübergehend zu sagen, dass es vorerst keine Fremdschlüssel prüfen soll.
Sie können die Fremdschlüsselprüfung mit dem folgenden Code deaktivieren:
FOREIGN_KEY_CHECKS=0
Um es wieder zu aktivieren, tun Sie dies:
FOREIGN_KEY_CHECKS=1