Ujednoznacznienie kolumn/ograniczeń dotyczących obcych kluczy
Zakładając, że masz na myśli ograniczenia klucza obcego , krótka odpowiedź brzmi:po prostu ich nie używasz .
I oto nadchodzi ten długi:
Jesteśmy przyzwyczajeni do odwoływania się do kolumn będących kluczami obcymi do innych stołów. Zwłaszcza podczas procesu normalizacji wyrażenia takie jak „user_purchase.i_id
jest kluczem obcym do items
stół” byłoby bardzo powszechne. Chociaż jest to całkowicie słuszny sposób na opisanie relacji, może być trochę niewyraźny, gdy dojdziemy do fazy wdrażania.
Załóżmy, że utworzyłeś tabele bez FOREIGN KEY
klauzule:
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,
);
Zauważ, że w relacji klucz obcy kolumny są nadal zaimplementowane . Jest kolumna, która odwołuje się do user
tabela (id
) i inny, który odwołuje się do items
tabela (i_id
) — wstawmy name
kolumnę na bok na chwilę. Weź pod uwagę następujące dane:
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 |
Związek istnieje. Jest realizowany za pomocą user_purchase
tabela zawierająca informacje o tym, kto co kupił . Gdybyśmy zapytali bazę danych o odpowiedni raport, zrobilibyśmy:
select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)
I tak używamy relacji i klucza obcego kolumny zaangażowanych.
A co, jeśli zrobimy:
insert into user_purchase (id,i_id) values (23,99)
Najwyraźniej jest to nieprawidłowy wpis. Chociaż istnieje użytkownik z id=23
, nie ma elementu z i_id=99
. RDBMS pozwoliłby na to, ponieważ nie wie nic lepszego . Już.
Właśnie tam ograniczenia klucza obcego wejść do gry. Określając FOREIGN KEY (i_id) REFERENCES items(i_id)
w user_purchase
definicji tabeli, zasadniczo dajemy RDBMS regułę, której należy przestrzegać:wpisy z i_id
wartości, które nie są zawarte w items.i_id
kolumny są niedopuszczalne . Innymi słowy, gdy klucz obcy kolumna implementuje odniesienie , klucz obcy ograniczenie wymusza integralność referencyjną .
Pamiętaj jednak, że powyższy select
nie zmieni się, tylko dlatego, że zdefiniowałeś ograniczenie FK. Tak więc ty nie używaj ograniczeń FK, tak jak robi to RDBMS, aby chronić swoje dane.
Zwolnienia
Zadaj sobie pytanie:dlaczego miałbyś tego chcieć? Jeśli dwa klucze obce mają służyć temu samemu celowi, nadmiarowość w końcu przysporzy ci kłopotów. Weź pod uwagę następujące dane:
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 |
Co jest nie tak z tym obrazem? Czy użytkownik 55
? kupić dwie tabliczki czekolady, czy tabliczkę czekolady i pastę do zębów? Ten rodzaj niejednoznaczności może wymagać dużego wysiłku, aby zachować synchronizację danych, co byłoby niepotrzebne, gdybyśmy zachowali tylko jeden z kluczy obcych. Właściwie, dlaczego nie porzucić name
w całości, ponieważ wynika to z relacji.
Oczywiście możemy rozwiązać ten problem, implementując złożony klucz obcy, ustawiając PRIMARY KEY(i_id,name)
dla items
tabela (lub zdefiniowanie dodatkowego UNIQUE(i_id,name)
indeks, to naprawdę nie ma znaczenia), a następnie ustawienie FOREIGN KEY(i_id,name) REFERENCES items(i_id,name)
. W ten sposób tylko (i_id,name) pary, które istnieją w items
tabela będzie ważna dla user_purchases
. Oprócz tego, że nadal miałbyś jeden klucz obcy , takie podejście jest całkowicie niepotrzebne, pod warunkiem, że i_id
kolumna jest już wystarczająca do zidentyfikowania pozycji (nie można powiedzieć tego samego dla name
kolumna...).
Jednak nie ma reguły przeciwko używaniu wielu kluczy obcych do tabeli. W rzeczywistości istnieją okoliczności, które wymagają takiego podejścia. Rozważ person(id,name)
stół i parent(person,father,mother)
jeden, z następującymi danymi:
person parent
| id name | | person father mother |
| 14 John | | 21 14 59 |
| 43 Jane | | 14 76 43 |
| 21 Mike |
| 76 Frank |
| 59 Mary |
Oczywiście wszystkie trzy kolumny parent
tabela to klucze obce dla person
. Nie dla tej samej relacji , ale dla trzech różnych :Ponieważ rodzice osoby są również osobami, dwie odpowiadające kolumny muszą odnosić się do tej samej tabeli person
robi. Pamiętaj jednak, że te trzy pola nie tylko mogą ale także musisz skieruj inną person
s w tym samym parent
awanturę, ponieważ nikt nie jest jego własnym rodzicem i nikt nie jest jego matką.