Fremdschlüsselspalten/Beschränkungsdisambiguierung
Angenommen, Sie beziehen sich auf die Fremdschlüsseleinschränkungen , wäre die kurze Antwort Sie verwenden sie einfach nicht .
Und hier kommt der lange:
Wir sind es gewohnt, von Spalten als Fremdschlüssel zu sprechen zu anderen Tischen. Insbesondere während des Normalisierungsprozesses können Sätze wie "user_purchase.i_id
ist ein Fremdschlüssel zu den items
Tabelle" wäre sehr verbreitet. Das ist zwar eine vollkommen gültige Art, die Beziehung zu beschreiben, aber es kann ein wenig verschwommen werden, wenn wir die Implementierungsphase erreichen.
Angenommen, Sie haben Ihre Tabellen ohne erstellt den FOREIGN KEY
Klauseln:
CREATE TABLE user(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
name TINYTEXT NOT NULL,
id INT(11) NOT NULL,
);
Beachten Sie, dass die Fremdschlüssel-Spalten relational sind sind immer noch implementiert . Es gibt eine Spalte, die auf user
verweist Tabelle (id
) und eine andere, die auf die items
verweist Tabelle (i_id
) -- setzen wir den name
ein Spalte für einen Moment beiseite. Betrachten Sie die folgenden Daten:
user user_purchase items
| id username | | id i_id | | i_id name price |
| 23 john | | 55 10 | | 10 chocolate bar 3.42 |
| 55 mary | | 70 10 | | 33 mobile phone 82.11 |
| 70 fred | | 70 33 | | 54 toothpaste 8.67 |
| 55 10 | | 26 toy car 6.00 |
| 70 26 |
Der Bezug ist da. Es wird über den user_purchase
implementiert Tabelle, die Informationen darüber enthält, wer was gekauft hat . Wenn wir die Datenbank nach einem relevanten Bericht abfragen würden, würden wir Folgendes tun:
select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)
Und so verwenden wir die Beziehung und die Fremdschlüsselspalten beteiligt.
Nun, was ist, wenn wir Folgendes tun:
insert into user_purchase (id,i_id) values (23,99)
Anscheinend handelt es sich um einen ungültigen Eintrag. Obwohl es einen Benutzer mit id=23
gibt , gibt es kein Element mit i_id=99
. Das RDBMS würde das zulassen, weil es es nicht besser weiß . Noch.
Das ist die Einschränkung für Fremdschlüssel komm in das Spiel. Durch Angabe von FOREIGN KEY (i_id) REFERENCES items(i_id)
im user_purchase
Tabellendefinition geben wir dem RDBMS im Wesentlichen eine zu befolgende Regel:Einträge mit i_id
Werte, die nicht in der items.i_id
enthalten sind Spalte sind nicht akzeptabel . Mit anderen Worten, während eine Fremdschlüsselspalte implementiert die Referenz , eine Fremdschlüssel-Einschränkung erzwingt die referenzielle Integrität .
Beachten Sie jedoch, dass Sie den obigen select
würde sich nicht ändern, nur weil Sie eine FK-Einschränkung definiert haben. Also, Sie Verwenden Sie keine FK-Einschränkungen, wie es das RDBMS tut, um Ihre Daten zu schützen.
Redundanzen
Frage dich:Warum willst du das? Wenn die beiden Fremdschlüssel denselben Zweck erfüllen sollen, bringt Sie die Redundanz irgendwann in Schwierigkeiten. Betrachten Sie die folgenden Daten:
user_purchase items
| id i_id name | | i_id name price |
| 55 10 chocolate bar | | 10 chocolate bar 3.42 |
| 70 10 chocolate bar | | 33 mobile phone 82.11 |
| 70 33 mobile phone | | 54 toothpaste 8.67 |
| 55 10 toothpaste | | 26 toy car 6.00 |
| 70 26 toy car |
Was ist falsch mit diesem Bild? Hat Benutzer 55
zwei Schokoriegel kaufen oder einen Schokoriegel und eine Zahnpasta? Diese Art von Mehrdeutigkeit kann zu viel Aufwand führen, um die Daten synchron zu halten, was unnötig wäre, wenn wir nur einen der Fremdschlüssel behalten würden. Warum nicht den name
weglassen Spalte zusammen, da dies durch die Relation impliziert wird.
Natürlich könnten wir dies lösen, indem wir einen zusammengesetzten Fremdschlüssel implementieren, indem wir PRIMARY KEY(i_id,name)
setzen für die items
Tabelle (oder Definition eines zusätzlichen UNIQUE(i_id,name)
Index, spielt keine Rolle) und dann einen FOREIGN KEY(i_id,name) REFERENCES items(i_id,name)
setzen . Auf diese Weise werden nur (i_id,name)-Paare angezeigt, die in den items
vorhanden sind Tabelle wäre für user_purchases
gültig . Abgesehen davon, dass man noch einen hätte Fremdschlüssel , ist dieser Ansatz völlig unnötig, vorausgesetzt, dass die i_id
Spalte reicht bereits aus, um ein Element zu identifizieren (dasselbe gilt nicht für den name
Spalte...).
Es spricht jedoch nichts dagegen, mehrere Fremdschlüssel für eine Tabelle zu verwenden. Tatsächlich gibt es Umstände, die ein solches Vorgehen erfordern. Stellen Sie sich eine person(id,name)
vor Tisch und ein parent(person,father,mother)
one, mit folgenden Daten:
person parent
| id name | | person father mother |
| 14 John | | 21 14 59 |
| 43 Jane | | 14 76 43 |
| 21 Mike |
| 76 Frank |
| 59 Mary |
Offensichtlich alle drei Spalten des parent
Tabelle sind Fremdschlüssel zu person
. Nicht für dieselbe Relation , aber für drei verschiedene :Da die Eltern einer Person ebenfalls Personen sind, müssen die beiden entsprechenden Spalten auf dieselbe Tabelle person
verweisen tut. Beachten Sie jedoch, dass die drei Felder nicht nur können sondern auch müssen andere person
verweisen s im selben parent
Reihe, da niemand sein eigener Elternteil ist und niemands Vater auch seine Mutter ist.