Czy klucz obcy może mieć wartość NULL i / lub być duplikatem?

325

Proszę wyjaśnić mi dwie rzeczy:

  1. Czy klucz obcy może mieć wartość NULL?
  2. Czy klucz obcy może być duplikatem?

O ile mi wiadomo, NULLnie powinien być używany w kluczach obcych, ale w niektórych moich aplikacjach mogę wprowadzać NULLzarówno Oracle, jak i SQL Server, i nie wiem dlaczego.

zacina się
źródło
1
@Adrian: Według mojej najlepszej wiedzy klucz obcy nie może mieć wartości NULL, ale przyjmuje wartość NULL w serwerze SQL i Oracle. czy możesz mi wytłumaczyć dlaczego?
dżemy
@Jams - przeczytaj link w mojej odpowiedzi.
JNK
11
nie można tego usunąć, ponieważ odpowiedzi i pytanie są przydatne. Edytuj pytanie, aby je poprawić.
Jeff Atwood
Proszę oddzielić pytanie o duplikaty. Tylko ta o NULL znajduje się poniżej.
reinierpost

Odpowiedzi:

527

Krótka odpowiedź: Tak, może być NULL lub zduplikowana.

Chcę wyjaśnić, dlaczego klucz obcy może być zerowy lub może być unikatowy. Najpierw pamiętaj, że klucz obcy wymaga po prostu, aby wartość w tym polu najpierw istniała w innej tabeli (tabeli nadrzędnej). To wszystko, co FK jest z definicji. Null z definicji nie jest wartością. Null oznacza, że ​​nie wiemy jeszcze, jaka jest wartość.

Pozwól, że dam ci przykład z prawdziwego życia. Załóżmy, że masz bazę danych, w której przechowywane są oferty sprzedaży. Załóżmy ponadto, że do każdej oferty przypisany jest tylko jeden sprzedawca i jeden klient. Tak więc tabela propozycji miałaby dwa klucze obce, jeden z identyfikatorem klienta i jeden z identyfikatorem przedstawiciela handlowego. Jednak w momencie tworzenia rekordu przedstawiciel handlowy nie zawsze jest przypisywany (ponieważ nikt nie jest jeszcze w stanie nad nim pracować), więc identyfikator klienta jest wypełniony, ale identyfikator przedstawiciela handlowego może być zerowy. Innymi słowy, zwykle potrzebujesz zdolności zerowego FK, gdy możesz nie znać jego wartości w momencie wprowadzania danych, ale znasz inne wartości w tabeli, które należy wprowadzić. Aby zezwolić na wartości zerowe w FK, ogólnie wszystko, co musisz zrobić, to zezwolić na wartości zerowe w polu, które ma FK. Wartość null jest oddzielna od idei, że jest to FK.

To, czy jest unikalne, czy nie, dotyczy tego, czy tabela ma relację jeden-jeden, czy jeden-wiele z tabelą nadrzędną. Teraz, jeśli masz relację jeden-jeden, możliwe, że możesz mieć wszystkie dane w jednej tabeli, ale jeśli tabela staje się zbyt szeroka lub jeśli dane dotyczą innego tematu (pracownik - przykład ubezpieczenia @tbone podał na przykład), to chcesz osobne tabele z FK. Następnie chciałbyś, aby ten FK był również PK (co gwarantuje wyjątkowość) lub nałożył na niego unikalne ograniczenie.

Większość FK jest przeznaczona dla relacji jeden do wielu i to właśnie otrzymujesz od FK bez dodawania dalszych ograniczeń w terenie. Masz więc na przykład tabelę zamówień i tabelę szczegółów zamówienia. Jeśli klient zamawia jednocześnie dziesięć produktów, ma on jedno zamówienie i dziesięć rekordów szczegółowych zamówień, które zawierają ten sam identyfikator zamówienia co FK.

HLGEM
źródło
13
Czy to ma być lepsze niż posiadanie fałszywego sprzedawcy o nazwie „Nieprzypisany”?
Thomas Weller,
8
Komentarz. Wartości null pozostawiają wiele miejsca na błędy w zapytaniu osób, które nie wiedzą, jak SQL (mis) obsługuje 3VL. Jeśli sprzedawca naprawdę nie jest konieczny do określonego stołu r, po prostu nie dołączasz tego rekordu. Osobną tabelą może być „WniosekAssignedTo” lub niektóre takie, z odpowiednimi ograniczeniami. Pisarz zapytań może następnie dołączyć do tej tabeli i podać własną logikę tego, co chcemy zrobić, gdy propozycja nie ma sprzedawcy. NULL nie oznacza tylko „nie wiemy” - może być używany do wielu rzeczy (dlatego prawie zawsze jest to zły pomysł)
N Zach.
26
@ nWest, nie pozwalam osobom niekompetentnym przesyłać zapytań do moich baz danych, a każdy programista, który nie wie, jak obsługiwać wartości zerowe, jest niekompetentny. Są chwile, kiedy dane nie są znane w momencie początkowego wprowadzania danych dla konkretnego pola, ale inne pola są w tym czasie potrzebne.
HLGEM
28
@ThomasWeller Odwoływanie się do fałszywego sprzedawcy („Nieprzypisany”) jeszcze bardziej pogarsza problem. Zakładam, że twoja tabela sprzedawcy ma wiele kolumn ...? Jaki jest numer ubezpieczenia społecznego pana Unassigned? Do którego działu jest przypisany? Kto jest jego szefem? Mam nadzieję, że rozumiesz: kiedy tworzysz „nieprzypisanego” sprzedawcę, szybko odkrywasz, że handlowałeś NULLjednym stołem za wiele NULLs w innym stole.
Gili
1
@ThomasWeller Będziesz mieć również problem, jeśli / kiedy będziesz potrzebować zlokalizować swój interfejs.
tobiv
45

Z pyska konia:

Klucze obce pozwalają na wartości kluczy, które są wszystkie NULL, nawet jeśli nie ma pasujących kluczy PODSTAWOWYCH lub UNIKALNYCH

Brak ograniczeń klucza obcego

Jeśli żadne klucze nie są zdefiniowane dla klucza obcego, dowolna liczba wierszy w tabeli podrzędnej może odwoływać się do tej samej wartości klucza nadrzędnego. Ten model dopuszcza wartości null w kluczu obcym. ...

Ograniczenie NOT NULL dotyczące klucza obcego

Gdy wartości null nie są dozwolone w kluczu obcym, każdy wiersz w tabeli potomnej musi jawnie odwoływać się do wartości w kluczu nadrzędnym, ponieważ wartości null nie są dozwolone w kluczu obcym.

Dowolna liczba wierszy w tabeli podrzędnej może odwoływać się do tej samej wartości klucza nadrzędnego, więc ten model ustanawia relację jeden do wielu między kluczem nadrzędnym a kluczem obcym. Jednak każdy wiersz w tabeli potomnej musi mieć odniesienie do wartości klucza nadrzędnego; brak wartości (null) w kluczu obcym jest niedozwolony. Ten sam przykład z poprzedniej sekcji można wykorzystać do zilustrowania takiego związku. Jednak w takim przypadku pracownicy muszą mieć odniesienie do określonego działu.

UNIKALNE ograniczenie na klucz obcy

Gdy dla klucza obcego zdefiniowane jest ograniczenie UNIKALNE, tylko jeden wiersz w tabeli potomnej może odwoływać się do danej wartości klucza nadrzędnego. Ten model dopuszcza wartości null w kluczu obcym.

Ten model ustanawia relację jeden-do-jednego między kluczem nadrzędnym a kluczem obcym, który pozwala na nieokreślone wartości (null) w kluczu obcym. Załóżmy na przykład, że tabela pracowników miała kolumnę MEMBERNO, odnoszącą się do numeru członkostwa pracownika w planie ubezpieczenia firmy. Ponadto tabela o nazwie UBEZPIECZENIE ma klucz podstawowy o nazwie MEMBERNO, a inne kolumny tabeli przechowują odpowiednie informacje dotyczące polisy ubezpieczeniowej pracownika. MEMBERNO w tabeli pracowników musi być zarówno kluczem obcym, jak i kluczem unikalnym:

  • Aby wymusić reguły integralności referencyjnej między tabelami EMP_TAB i UBEZPIECZENIA (ograniczenie KLUCZ OBCY)

  • Aby zagwarantować, że każdy pracownik ma unikalny numer członkowski (ograniczenie klucza UNIKALNE)

UNIKALNE i NIE ZEROWANE Ograniczenia dotyczące klucza obcego

Gdy w kluczu obcym zdefiniowane są ograniczenia UNIQUE i NOT NULL, tylko jeden wiersz w tabeli potomnej może odwoływać się do danej wartości klucza nadrzędnego, a ponieważ wartości NULL nie są dozwolone w kluczu obcym, każdy wiersz w tabeli potomnej musi jawnie odwoływać się wartość w kluczu nadrzędnym.

Zobacz:

Łącze Oracle 11g

tbone
źródło
16

Tak, klucz obcy może być zerowy, jak powiedziano powyżej przez starszych programistów ... Dodałbym inny scenariusz, w którym klucz obcy będzie wymagał wartości null .... załóżmy, że mamy w tabelach komentarze, zdjęcia i filmy, które pozwalają na komentarze do zdjęć i filmy. W tabeli komentarzy możemy mieć dwa klucze obce PicturesId i VideosId wraz z głównym kluczem CommentId. Więc kiedy komentujesz wideo, wymagane będzie tylko VideoId, a pictureId będzie zerowe ... a jeśli skomentujesz zdjęcie, wymagane będzie tylko PictureId, a WideoID będzie zerowe ...

Touseef Ahmed Awan
źródło
1
Myślę, że istnieje lepszy sposób na rozwiązanie tego problemu. Zamiast tworzyć nowe kolumny, możesz mieć dwie kolumny, a mianowicie „id” i „typ”, które będą zawierać identyfikator i nazwę tabeli kluczy obcych. Np. Id = 1, type = Obraz będzie reprezentował link do tabeli obrazów o id 1. Zaletą korzystania z tego rozwiązania jest to, że nie trzeba tworzyć nowych kolumn, gdy komentarze są dodawane do dodatkowych tabel. Wadą nie będzie ograniczenia klucza obcego na poziomie db, raczej ograniczenie będzie musiało być na poziomie aplikacji.
Agent47DarkSoul
4
@Agent: Mieliśmy to „rozwiązanie” w zastosowaniach produkcyjnych. Nie rób tego, to okropne. Tworzenie zapytań staje się takim bałaganem, że „jeśli jest typu 1, dołącz do tej tabeli, w przeciwnym razie dołącz do tego”. To był dla nas koszmar. W końcu zrobiliśmy to, co mówi ta odpowiedź i utworzyliśmy nową kolumnę dla każdego rodzaju złączenia. Tworzenie kolumn jest tanie. W zasadzie to tylko wada, że ​​wiele kolumn sprawia, że ​​Toad jest trudny w użyciu, ale to tylko wada Toada.
user128216,
1
@FighterJet Rails zapewnia doskonałą strukturę ORM, która obsługuje nawet skomplikowane zapytania dzięki temu rozwiązaniu.
Agent47DarkSoul
2
@Agent: Może to może ... ale jeśli możesz to uprościć, po co komplikować? A może „koszmar” było niewłaściwym słowem: było po prostu bardzo niewygodne. Nie mieliśmy problemów z integralnością danych (dużo).
user128216,
7

zależy to od roli, jaką odgrywa to foreign keyw twoim związku.

  1. jeśli foreign keyjest to również key attributew twoim związku, to nie może być NULL
  2. jeśli foreign keyjest to normalny atrybut w relacji, może mieć wartość NULL.
shinxg
źródło
3

Oto przykład z wykorzystaniem składni Oracle:
Najpierw stwórzmy tabelę COUNTRY

CREATE TABLE TBL_COUNTRY ( COUNTRY_ID VARCHAR2 (50) NOT NULL ) ;
ALTER TABLE TBL_COUNTRY ADD CONSTRAINT COUNTRY_PK PRIMARY KEY ( COUNTRY_ID ) ;

Utwórz tabelę PROWINCJA

CREATE TABLE TBL_PROVINCE(
PROVINCE_ID VARCHAR2 (50) NOT NULL ,
COUNTRY_ID  VARCHAR2 (50)
);
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_PK PRIMARY KEY ( PROVINCE_ID ) ;
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_COUNTRY_FK FOREIGN KEY ( COUNTRY_ID ) REFERENCES TBL_COUNTRY ( COUNTRY_ID ) ;

Działa to doskonale w Oracle. Zauważ, że klucz obcy COUNTRY_ID w drugiej tabeli nie ma „NOT NULL”.

Teraz, aby wstawić wiersz do tabeli PROVINCE, wystarczy podać tylko PROVINCE_ID. Jeśli jednak zdecydujesz się również określić COUNTRY_ID, musi on już istnieć w tabeli COUNTRY.

Mouhcine
źródło
1

Domyślnie klucz obcy nie ma żadnych ograniczeń, klucz obcy może być zerowy i zduplikowany.

podczas tworzenia tabeli / zmieniania tabeli, jeśli dodasz jakiekolwiek ograniczenie niepowtarzalności lub nie będzie miało wartości pustej, tylko ona nie pozwoli na wartości zerowe / zduplikowane.

nitin lalwani
źródło
0

Mówiąc najprościej, „Nieidentyfikujące” relacje między Jednostkami są częścią Modelu ER i są dostępne w Microsoft Visio podczas projektowania Diagramu ER. Jest to wymagane w celu wymuszenia liczności między jednostkami typu „zero lub więcej niż zero” lub „zero lub jeden”. Zwróć uwagę na to „zero” liczności zamiast „jeden” na „jeden do wielu”.

Otóż ​​przykładem relacji nieidentyfikującej, w której liczność może być „zero” (brak identyfikacji), jest przypadek, gdy mówimy, że rekord / obiekt w jednej encji - „może” lub „może nie” mieć wartości jako odniesienia do rekordu / s w innym podmiocie B.

Ponieważ istnieje możliwość, że jeden rekord bytu-A identyfikuje się z zapisami innego bytu-B, dlatego powinna istnieć kolumna w bycie-bicie zawierająca wartość tożsamości rekordu bytu-B. Ta kolumna może mieć wartość „Null”, jeśli żaden rekord w Jednostce A nie identyfikuje rekordu (ów) lub obiektu (ów) w Jednostce B.

W paradygmacie zorientowanym obiektowo (świat rzeczywisty) zdarzają się sytuacje, w których obiekt klasy B niekoniecznie zależy (silnie sprzężony) od obiektu klasy A pod względem istnienia, co oznacza, że ​​klasa B jest luźno sprzężona z klasą Taki, że Klasa A może „zawierać” (Przechowywać) obiekt klasy A, w przeciwieństwie do pojęcia przedmiotu klasy B, musi mieć (Skład) obiekt klasy A, ponieważ (obiekt klasy- B) stworzenie.

Z punktu widzenia zapytania SQL można wyszukiwać wszystkie rekordy w jednostce B, które nie mają wartości null, dla klucza obcego zarezerwowanego dla jednostki B. Spowoduje to, że wszystkie rekordy posiadające pewną odpowiednią wartość dla wierszy w jednostce A lub alternatywnie wszystkie rekordy o wartości Null będą rekordami, które nie mają żadnych rekordów w jednostce A w jednostce B.

Fachar
źródło
-1

Myślę, że lepiej jest wziąć pod uwagę możliwą liczność, jaką mamy w tabelach. Możemy mieć możliwą minimalną liczebność zerową. Gdy jest to opcjonalne, minimalny udział krotek z powiązanej tabeli może wynosić zero. Teraz stajesz przed koniecznością, aby wartości klucza obcego były zerowe.

Ale odpowiedź brzmi: wszystko zależy od biznesu.

użytkownik9274383
źródło
-3

Idea klucza obcego opiera się na koncepcji odwoływania się do wartości, która już istnieje w głównej tabeli. Dlatego w drugiej tabeli jest nazywany kluczem obcym. Ta koncepcja nazywa się integralnością referencyjną. Jeśli klucz obcy zostanie zadeklarowany jako pole zerowe, naruszy to samą logikę integralności referencyjnej. Co to będzie dotyczyło? Może odnosić się tylko do czegoś, co jest obecne w głównej tabeli. Dlatego myślę, że błędem byłoby zadeklarowanie pola klucza obcego jako pustego.

SQLDev
źródło
Może odwoływać się do „niczego” lub nie znasz jeszcze jego wartości NULL, ale integralność referencyjna mówi, że jeśli odwołuje się do „czegoś”, musi tam być.
yaxe
-7

Myślę, że klucz obcy z jednej tabeli jest również kluczem podstawowym do innej tabeli, więc nie pozwala na wartości null, więc nie ma mowy o wartości null w kluczu obcym.

użytkownik4532553
źródło