sql >> Database >  >> RDS >> Mysql

Hoe buitenlandse sleutels te gebruiken met PHP

Buitenlandse sleutelkolommen/beperkingen ondubbelzinnig maken

Ervan uitgaande dat u verwijst naar de externe sleutelbeperkingen , zou het korte antwoord zijn:je gebruikt ze gewoon niet .

En hier komt de lange:

We zijn gewend om te verwijzen naar kolommen als externe sleutels naar andere tafels. Vooral tijdens het normalisatieproces kunnen zinnen als "user_purchase.i_id is een externe sleutel voor de items tafel" zou heel gebruikelijk zijn. Hoewel dat een perfect geldige manier is om de relatie te beschrijven, kan het een beetje vaag worden wanneer we de implementatiefase bereiken.

Stel dat u uw tabellen zonder . heeft gemaakt de FOREIGN KEY clausules:

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,
);

Merk op dat de externe sleutel kolommen zijn nog steeds geïmplementeerd . Er is een kolom die verwijst naar de user tabel (id ) en een andere die verwijst naar de items tabel (i_id ) -- laten we de name kolom even opzij. Houd rekening met de volgende gegevens:

  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  |

De relatie is er. Het wordt geïmplementeerd door middel van de user_purchase tabel, die informatie bevat over wie wat heeft gekocht . Als we de database zouden opvragen voor een relevant rapport, zouden we het volgende doen:

select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)

En zo gebruiken we de relatie en de refererende sleutel kolommen betrokken.

Wat als we nu doen:

insert into user_purchase (id,i_id) values (23,99)

Blijkbaar is dit een ongeldige invoer. Hoewel er een gebruiker is met id=23 , er is geen item met i_id=99 . Het RDBMS zou dat mogelijk maken, omdat het niet beter weet . Nog.

Dat is waar beperkingen voor buitenlandse sleutels in het spel komen. Door FOREIGN KEY (i_id) REFERENCES items(i_id) op te geven in de user_purchase tabeldefinitie, geven we het RDBMS in wezen een regel die moet worden gevolgd:invoeren met i_id waarden die niet zijn opgenomen in de items.i_id kolom zijn niet acceptabel . Met andere woorden, terwijl een externe sleutel kolom implementeert de referentie , een beperking . met een externe sleutel handhaaft de referentiële integriteit .

Merk echter op dat de bovenstaande select niet zou veranderen, alleen omdat je een FK-beperking definieerde. Dus, jij gebruik geen FK-beperkingen, het RDBMS wel, om uw gegevens te beschermen.

Ontslagen

Stel jezelf de vraag:waarom zou je dat willen? Als de twee externe sleutels hetzelfde doel dienen, zal de redundantie u uiteindelijk in de problemen brengen. Houd rekening met de volgende gegevens:

 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        |

Wat is er mis met deze foto? Heeft gebruiker 55 twee chocoladerepen kopen, of een chocoladereep en een tandpasta? Dit soort ambiguïteit kan leiden tot veel moeite om gegevens synchroon te houden, wat niet nodig zou zijn als we slechts een van de externe sleutels zouden behouden. In feite, waarom laat je de name niet vallen? kolom helemaal, omdat het wordt geïmpliceerd door de relatie.

We kunnen dit natuurlijk oplossen door een samengestelde externe sleutel te implementeren, door PRIMARY KEY(i_id,name) in te stellen voor de items tabel (of het definiëren van een extra UNIQUE(i_id,name) index, het maakt niet echt uit) en stel vervolgens een FOREIGN KEY(i_id,name) REFERENCES items(i_id,name) in . Op deze manier zijn alleen (i_id,name) koppels die voorkomen in de items tabel zou geldig zijn voor user_purchases . Afgezien van het feit dat je nog steeds één . zou hebben buitenlandse sleutel , is deze aanpak totaal overbodig, op voorwaarde dat de i_id kolom is al voldoende om een ​​item te identificeren (kan niet hetzelfde zeggen voor de name kolom...).

Er is echter geen regel tegen het gebruik van meerdere externe sleutels voor een tabel. In feite zijn er omstandigheden die een dergelijke benadering vereisen. Overweeg een person(id,name) tafel en een parent(person,father,mother) één, met de volgende gegevens:

 person             parent
| id  name    |    | person  father  mother |
| 14  John    |    |   21      14      59   |
| 43  Jane    |    |   14      76      43   |
| 21  Mike    |
| 76  Frank   |
| 59  Mary    |

Het is duidelijk dat alle drie de kolommen van de parent tabel zijn externe sleutels naar person . Niet voor dezelfde relatie , hoewel, maar voor drie verschillende :Aangezien de ouders van een persoon ook personen zijn, moeten de twee corresponderende kolommen verwijzen naar dezelfde tabel person doet. Merk echter op dat de drie velden niet alleen kunnen maar ook moeten verwijs andere person s in dezelfde parent rij, aangezien niemand zijn eigen ouder is en niemands vader ook zijn moeder is.



  1. Voeg 6 uur toe aan de functie now()

  2. Sp_help_jobschedule gebruiken in SQL Server

  3. Hoe informatie te krijgen over compileerfouten in Oracle/TOAD

  4. alembic util-opdrachtfout kan id niet vinden