Disambiguering av främmande nyckelkolumner/begränsningar
Förutsatt att du hänvisar till restriktioner för främmande nyckel , det korta svaret skulle vara du använder dem bara inte .
Och här kommer den långa:
Vi är vana vid att hänvisa till att kolumner är främmande nycklar till andra bord. Särskilt under normaliseringsprocessen, fraser som "user_purchase.i_id
är en främmande nyckel till items
tabell" skulle vara mycket vanligt. Även om det är ett helt giltigt sätt att beskriva förhållandet, kan det bli lite flummigt när vi når implementeringsfasen.
Anta att du har skapat dina tabeller utan 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,
);
Lägg märke till att, relationsmässigt, kolumnerna med främmande nyckel är fortfarande implementerade . Det finns en kolumn som refererar till user
tabell (id
) och en annan som refererar till items
tabell (i_id
) -- låt oss lägga in name
kolumnen åt sidan för ett ögonblick. Tänk på följande 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 |
Relationen finns där. Det implementeras med hjälp av user_purchase
tabell, som innehåller information om vem som köpte vad . Om vi skulle fråga databasen efter en relevant rapport, skulle vi göra:
select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)
Och det är så vi använder relationen och kolumnerna med främmande nyckel involverade.
Vad händer nu om vi gör:
insert into user_purchase (id,i_id) values (23,99)
Tydligen är detta en ogiltig post. Även om det finns en användare med id=23
, det finns inget objekt med i_id=99
. RDBMS skulle tillåta det att hända, eftersom det inte vet bättre . Än.
Det är där främmande nyckel begränsningar komma till spel. Genom att ange FOREIGN KEY (i_id) REFERENCES items(i_id)
i user_purchase
tabelldefinition ger vi i huvudsak RDBMS en regel att följa:poster med i_id
värden som inte finns i items.i_id
kolumner är inte acceptabla . Med andra ord, medan en främmande nyckel kolumn implementerar referensen , en främmande nyckel begränsning upprätthåller referensintegriteten .
Observera dock att ovanstående select
skulle inte ändras, bara för att du definierade en FK-begränsning. Alltså du använd inte FK-begränsningar, det gör RDBMS för att skydda dina data.
Uppsägningar
Fråga dig själv:Varför skulle du vilja det? Om de två främmande nycklarna ska tjäna samma syfte kommer redundansen så småningom att få dig i trubbel. Tänk på följande 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 |
Vad är det för fel på den här bilden? Gjorde användaren 55
köpa två chokladkakor, eller en chokladkaka och en tandkräm? Denna typ av oklarhet kan leda till mycket ansträngning för att hålla data synkroniserade, vilket skulle vara onödigt om vi bara behöll en av de främmande nycklarna. Faktum är att varför inte släppa name
kolumn helt och hållet, eftersom det antyds av relationen.
Naturligtvis skulle vi kunna lösa detta genom att implementera en sammansatt främmande nyckel, genom att ställa in PRIMARY KEY(i_id,name)
för items
tabell (eller definiera en extra UNIQUE(i_id,name)
index, det spelar ingen roll) och ställ sedan in en FOREIGN KEY(i_id,name) REFERENCES items(i_id,name)
. På detta sätt är endast (i_id,name) par som finns i items
Tabellen skulle vara giltig för user_purchases
. Förutom det faktum att du fortfarande skulle ha en främmande nyckel , är detta tillvägagångssätt helt onödigt, förutsatt att i_id
kolumnen räcker redan för att identifiera ett objekt (kan inte säga detsamma för name
kolumn...).
Det finns dock ingen regel mot att använda flera främmande nycklar till en tabell. Det finns faktiskt omständigheter som kräver ett sådant tillvägagångssätt. Tänk på en person(id,name)
tabell och en parent(person,father,mother)
en, med följande data:
person parent
| id name | | person father mother |
| 14 John | | 21 14 59 |
| 43 Jane | | 14 76 43 |
| 21 Mike |
| 76 Frank |
| 59 Mary |
Uppenbarligen alla tre kolumnerna i parent
tabellen är främmande nycklar till person
. Inte för samma relation , dock, men för tre olika :Eftersom en persons föräldrar också är personer måste de två motsvarande kolumnerna referera till samma tabell person
gör. Observera dock att de tre fälten inte bara kan men också måste hänvisa till annan person
s i samma parent
rad, eftersom ingen är hans egen förälder och ingens far är hans mamma också.