Disambiguation af fremmednøglekolonner/-begrænsninger
Forudsat at du henviser til de fremmednøglebegrænsninger , ville det korte svar være du bruger dem bare ikke .
Og her kommer den lange:
Vi er vant til at henvise til, at kolonner er fremmednøgler til andre borde. Især under normaliseringsprocessen, sætninger som "user_purchase.i_id
er en fremmednøgle til items
tabel" ville være meget almindeligt. Selvom det er en helt gyldig måde at beskrive forholdet på, kan det blive lidt uklart, når vi når implementeringsfasen.
Antag, at du har oprettet dine tabeller uden FOREIGN KEY
klausuler:
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,
);
Bemærk, at relationsmæssigt er fremmednøglen kolonner er stadig implementeret . Der er en kolonne, der refererer til user
tabel (id
) og en anden, der refererer til items
tabel (i_id
) -- lad os sætte name
kolonne til side et øjeblik. Overvej følgende data:
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 |
Forholdet er der. Det implementeres ved hjælp af user_purchase
tabel, som indeholder oplysninger om hvem købte hvad . Hvis vi skulle forespørge databasen for en relevant rapport, ville vi gøre:
select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)
Og det er sådan, vi bruger relationen og fremmednøgle kolonner involveret.
Hvad nu hvis vi gør:
insert into user_purchase (id,i_id) values (23,99)
Tilsyneladende er dette en ugyldig post. Selvom der er en bruger med id=23
, der er intet element med i_id=99
. RDBMS ville tillade det at ske, fordi det ved ikke bedre . Endnu.
Det er her fremmednøgle begrænsninger komme i spil. Ved at angive FOREIGN KEY (i_id) REFERENCES items(i_id)
i user_purchase
tabeldefinition, giver vi i det væsentlige RDBMS en regel at følge:indgange med i_id
værdier, der ikke er indeholdt i items.i_id
kolonne er ikke acceptable . Med andre ord, mens en fremmednøgle kolonne implementerer referencen , en fremmednøgle begrænsning håndhæver henvisningsintegriteten .
Bemærk dog, at ovenstående select
ville ikke ændre sig, bare fordi du definerede en FK-begrænsning. Således dig brug ikke FK-begrænsninger, det gør RDBMS for at beskytte dine data.
Afskedigelser
Spørg dig selv:Hvorfor vil du det? Hvis de to fremmednøgler skal tjene det samme formål, vil redundansen i sidste ende få dig i problemer. Overvej følgende data:
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 |
Hvad er der galt med dette billede? Gjorde bruger 55
købe to chokoladebarer, eller en chokoladebar og en tandpasta? Denne form for tvetydighed kan føre til en stor indsats for at holde data synkroniseret, hvilket ville være unødvendigt, hvis vi bare beholdt en af fremmednøglerne. Faktisk, hvorfor ikke droppe name
kolonne helt, da det er underforstået af relationen.
Selvfølgelig kunne vi løse dette ved at implementere en sammensat fremmednøgle ved at indstille PRIMARY KEY(i_id,name)
for items
tabel (eller definere en ekstra UNIQUE(i_id,name)
indeks, er det ligegyldigt) og derefter indstille en FOREIGN KEY(i_id,name) REFERENCES items(i_id,name)
. På denne måde er det kun (i_id,name) par, der findes i items
tabel ville være gyldig for user_purchases
. Bortset fra det faktum, at du stadig ville have en fremmednøgle , er denne tilgang fuldstændig unødvendig, forudsat at i_id
kolonnen er allerede nok til at identificere et element (kan ikke sige det samme for name
kolonne...).
Der er dog ingen regel mod at bruge flere fremmednøgler til en tabel. Faktisk er der omstændigheder, der kræver en sådan tilgang. Overvej en person(id,name)
tabel og en parent(person,father,mother)
en med følgende data:
person parent
| id name | | person father mother |
| 14 John | | 21 14 59 |
| 43 Jane | | 14 76 43 |
| 21 Mike |
| 76 Frank |
| 59 Mary |
Det er klart, at alle tre kolonner i parent
tabel er fremmednøgler til person
. Ikke for samme relation , dog, men for tre forskellige :Da en persons forældre også er personer, skal de to tilsvarende kolonner referere til den samme tabel person
gør. Bemærk dog, at de tre felter ikke kun kan men også skal henvis anden person
er i samme parent
række, da ingen er hans egen forælder, og ingens far også er hans mor.