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

Verwendung von Fremdschlüsseln mit PHP

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.