Yabancı anahtar NULL ve / veya çoğaltılabilir mi?


325

Lütfen benim için iki şeyi açıklığa kavuşturun:

  1. Yabancı anahtar NULL olabilir mi?
  2. Yabancı anahtar kopyalanabilir mi?

Bildiğim kadarıyla, NULLyabancı anahtarlarda kullanılmamalı, ancak bazı uygulamalarda NULLhem Oracle hem de SQL Server'a girebiliyorum ve nedenini bilmiyorum.


1
@Adrian: Bildiğim kadarıyla yabancı anahtar boş olamaz ama sql server ve kehanette boştur. nedenini açıklayabilir misin?
reçeller

@ Jams - cevabımdaki bağlantıyı oku.
JNK

11
cevaplar ve soru faydalı olduğu için bu silinemez. Soruyu geliştirmek için düzenlemekten çekinmeyin.
Jeff Atwood

Lütfen kopyalarla ilgili soruyu bölün. Aşağıda sadece NULL'larla ilgili cevap verilmiştir.
reinierpost

Yanıtlar:


529

Kısa cevap: Evet, NULL veya yinelenebilir.

Yabancı bir anahtarın neden boş veya benzersiz olması gerekip gerekmediğini açıklamak istiyorum. İlk olarak, bir Yabancı anahtarın yalnızca bu alandaki değerin farklı bir tabloda (üst tablo) var olmasını gerektirdiğini unutmayın. Hepsi bir FK tanım gereğidir. Tanım gereği null bir değer değildir. Null, değerin ne olduğunu henüz bilmediğimiz anlamına gelir.

Size gerçek bir hayat örneği vereyim. Satış tekliflerini depolayan bir veritabanınız olduğunu varsayalım. Ayrıca, her teklifin yalnızca bir satış görevlisi ve bir müşteri olduğunu varsayalım. Bu nedenle, teklif tablonuzda biri müşteri kimliğine, diğeri satış temsilcisi kimliğine sahip iki yabancı anahtar bulunur. Ancak, kayıt oluşturulduğu zaman, bir satış temsilcisi her zaman atanmaz (henüz kimse üzerinde çalışmakta serbest olduğu için), bu nedenle istemci kimliği doldurulur, ancak satış temsilcisi kimliği boş olabilir. Diğer bir deyişle, genellikle veri girildiği sırada değerini bilmediğinizde boş bir FK'ye sahip olmanız gerekir, ancak tablodaki girilmesi gereken diğer değerleri biliyorsunuzdur. Bir FK'de null değerlerine izin vermek için genellikle tek yapmanız gereken FK'ye sahip alanda null değerlerine izin vermektir. Boş değer, bir FK olduğu fikrinden ayrıdır.

Benzersiz olup olmadığı, tablonun ana tabloyla bir veya bir veya çok sayıda ilişkisi olup olmadığı ile ilgilidir. Tek bir ilişkiniz varsa, verilerin tümünü tek bir tabloda toplamanız mümkündür, ancak tablo çok genişliyorsa veya veriler farklı bir konuysa (çalışan - sigorta örneği @tbone verdi örneğin), FK içeren ayrı tablolar istersiniz. Daha sonra bu FK'yi aynı zamanda PK (benzersizliği garanti eden) yapmak veya benzersiz bir kısıtlama koymak istersiniz.

Çoğu FK bire çok ilişki içindir ve sahada bir kısıtlama eklemeden bir FK'den elde ettiğiniz şey budur. Yani bir sipariş tablonuz ve örneğin sipariş detayları tablonuz var. Müşteri bir seferde on ürün sipariş ederse, FK ile aynı orderID'yi içeren bir sipariş ve on sipariş detay kaydı vardır.


13
Yani bu "Atanmamış" adında sahte bir satış elemanına sahip olmaktan daha mı iyi?
Thomas Weller

8
Bir yorum. Null'lar, SQL'in (mis) 3VL'yi nasıl işlediğini bilmeyen kişiler tarafından sorgudaki hatalar için çok fazla alan bırakır. Bir satış görevlisi belirli bir r-tablosu için gerçekten gerekli değilse, sadece o kaydı dahil etmezsiniz. Ayrı bir tablo, uygun kısıtlamalarla "ProposalAssignedTo" veya benzeri bir tablo olabilir. Bir sorgu yazarı daha sonra bu tabloya katılabilir ve bir teklifin satış temsilcisi olmadığında yapmak istediğimiz her şey için kendi mantığını sağlayabilir. NULL sadece "bilmiyoruz" anlamına gelmez - birçok şey için kullanılabilir (bu yüzden neredeyse her zaman kötü bir fikirdir)
N West

26
@nWest, beceriksiz olan insanların veritabanlarımı sorgulamasına izin vermem ve boş değerlerle nasıl başa çıkacağını bilmeyen herhangi bir geliştirici yetersizdir. Belirli bir alan için ilk veri girişi sırasında verilerin bilinmediği, ancak o sırada diğer alanlara ihtiyaç duyulduğu zamanlar vardır.
HLGEM

28
@ThomasWeller Sahte bir satış görevlisine ("Atanmadı") başvurmak sorunu daha da kötüleştirir. Satış görevlisi tablonuzda birden çok sütun var ...? Bay Unassigned'in sosyal sigorta numarası nedir? Hangi bölüme atandı? Patronu kim? Demek istediğimi anlıyorum: "Atanmamış" bir satış elemanı oluşturduğunuzda, hızlı bir şekilde farklı bir tabloda NULLbirden çok NULLs için bir tabloda işlem yaptığınızı keşfedersiniz .
Gili

1
@ThomasWeller Arayüzünüzü yerelleştirmeniz gerektiğinde / ne zaman bir sorunla karşılaşırsınız.
tobiv


45

Atın ağzından:

Yabancı anahtarlar, eşleşen PRIMARY veya UNIQUE anahtar olmasa bile tümü NULL olan anahtar değerlerine izin verir

Yabancı Anahtarda Kısıtlama Yok

Yabancı anahtarda başka bir sınır tanımlanmadığında, alt tablodaki herhangi bir sayıda satır aynı üst anahtar değerine başvurabilir. Bu model yabancı anahtarda boş değerlere izin verir. ...

Yabancı Anahtarda BOŞ NULL Kısıtlama

Yabancı anahtarda null değerlerine izin verilmediğinde, alt tablodaki her satırın yabancı anahtarda null değerlerine izin verilmediğinden, üst anahtardaki bir değere açıkça başvurması gerekir.

Alt tablodaki herhangi bir sayıda satır aynı üst anahtar değerine başvurabilir, bu nedenle bu model üst ve yabancı anahtarlar arasında bire çok ilişki kurar. Ancak, alt tablodaki her satırın bir üst anahtar değerine başvurması gerekir; yabancı anahtarda bir değerin (null) olmamasına izin verilmez. Önceki bölümdeki aynı örnek, böyle bir ilişkiyi göstermek için kullanılabilir. Ancak, bu durumda, çalışanların belirli bir departmana referans vermesi gerekir.

EŞSİZ Yabancı Anahtar Kısıtlaması

Yabancı anahtarda bir UNIQUE kısıtlaması tanımlandığında, alt tabloda yalnızca bir satır belirli bir üst anahtar değerine başvurabilir. Bu model yabancı anahtarda boş değerlere izin verir.

Bu model, ana anahtar ile yabancı anahtarlar arasında, yabancı anahtarda belirlenmemiş değerlere (null) izin veren bire bir ilişki kurar. Örneğin, çalışan tablosunda MEMBERNO adlı bir sütun bulunduğunu ve şirket sigorta planındaki çalışan üyelik numarasına atıfta bulunduğunu varsayın. Ayrıca, INSURANCE adlı bir tablonun MEMBERNO adlı birincil bir anahtarı vardır ve tablonun diğer sütunları çalışan sigorta poliçesi ile ilgili bilgileri tutar. Çalışan tablosundaki MEMBERNO, hem yabancı bir anahtar hem de benzersiz bir anahtar olmalıdır:

  • EMP_TAB ve SİGORTA tabloları arasında başvuru bütünlüğü kurallarını zorunlu kılmak için (FOREIGN KEY kısıtlaması)

  • Her çalışanın benzersiz bir üyelik numarasına sahip olmasını sağlamak için (UNIQUE anahtar kısıtı)

UNIQUE ve NULL DEĞİL Yabancı Anahtardaki Kısıtlamalar

Yabancı anahtarda UNIQUE ve NOT NULL kısıtlamaları tanımlandığında, alt tablodaki yalnızca bir satır belirli bir üst anahtar değerine başvurabilir ve yabancı anahtarda NULL değerlere izin verilmediğinden, alt tablodaki her satır açıkça başvuruda bulunmalıdır üst anahtardaki bir değer.

Bunu gör:

Oracle 11g bağlantısı


16

Evet yabancı anahtar üst düzey programcılar tarafından yukarıda anlatıldığı gibi boş olabilir ... Yabancı anahtar null olması gereken başka bir senaryo eklemek istiyorum .... varsayalım tablolar resimler, Resimler ve videolar üzerinde yorum izin veren bir uygulama ve videolar. Yorumlar tablosunda, birincil Anahtar CommentId ile birlikte iki Yabancı Anahtar PicturesId ve VideosId olabilir. Bu yüzden bir videoya yorum yaptığınızda yalnızca VideosId gerekir ve pictureId boş olur ... ve bir resme yorum yaparsanız sadece PictureId gerekir ve VideosId boş olur ...


1
Bu sorunu çözmenin daha iyi bir yolu olduğunu düşünüyorum. Yeni sütunlar oluşturmak yerine, yabancı anahtar tablosunun kimliğini ve adını içeren "id" ve "type" olmak üzere iki sütununuz olabilir. Örneğin, id = 1, type = Resim, id 1 ile Resim tablosuna bağlantıyı temsil edecektir. Bu çözümü kullanmanın avantajı, yorumlar ek tablolara eklendiğinde yeni sütunlar oluşturmanız gerekmeyecektir. Dezavantaj, db düzeyinde yabancı anahtar kısıtlaması olmayacak, bunun yerine kısıtlamanın uygulama seviyesi olması gerekecektir.
Ajan47DarkSoul

4
@Agent: Üretim kullanımında bu "çözüme" sahibiz. Yapma, korkunç. "Tür 1 ise, bu tabloya katıl, aksi takdirde buna katıl" sorguları yapmak bu karışıklık haline gelir. Bizim için bir kabustu. Bu cevabın söylediklerini bitirdik ve her bir katılma türü için yeni bir sütun oluşturduk. Sütun oluşturmak ucuzdur. Hemen hemen tek kusur, çok sayıda sütunun Toad'ı kullanımını zorlaştırmasıdır, ancak bu sadece Toad'ın bir kusuru.
user128216

1
@FighterJet Rails, bu çözümle karmaşık sorguları bile işleyen harika bir ORM çerçevesi sağlar.
Ajan47DarkSoul

2
@Agent: Belki yapabilir ... ama basitleştirebilirseniz, neden karmaşık hale getirmelisiniz? Ve belki de "kabus" kullanmak için yanlış bir kelimeydi: sadece çok rahatsız ediciydi. Veri bütünlüğü sorunları yaşamadık (çok fazla).
user128216

7

bunun foreign keyilişkinizde ne gibi bir rol oynadığına bağlıdır .

  1. eğer bu foreign keyda key attributeilişkinizde bir ise, o zaman NULL olamaz
  2. Bu takdirde foreign keysizin ilişkili olarak normal bir özelliktir, o zaman null olabilir.

3

Oracle sözdizimini kullanan bir örnek:
İlk önce bir tablo oluşturalım COUNTRY

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

PROVINCE tablosunu oluşturun

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

Bu Oracle'da mükemmel bir şekilde çalışıyor. İkinci tablodaki COUNTRY_ID yabancı anahtarının "NOT NULL" olmadığına dikkat edin.

Şimdi PROVINCE tablosuna bir satır eklemek için yalnızca PROVINCE_ID değerini belirtmek yeterlidir. Ancak, bir COUNTRY_ID belirtmeyi de seçtiyseniz, bunun COUNTRY tablosunda zaten var olması gerekir.


1

Varsayılan olarak yabancı anahtar üzerinde herhangi bir kısıtlama yoktur, yabancı anahtar boş ve kopya olabilir.

bir tablo oluştururken / tabloyu değiştirirken, herhangi bir benzersizlik kısıtlaması eklerseniz veya null değilse, yalnızca boş / yinelenen değerlere izin vermez.


0

Basitçe söylemek gerekirse, Varlıklar arasındaki "tanımlayıcı olmayan" ilişkiler ER-Model'in bir parçasıdır ve ER-Diagram tasarlanırken Microsoft Visio'da kullanılabilir. Bu, "sıfır veya sıfırdan büyük" veya "sıfır veya bir" türündeki varlıklar arasındaki kardinalliği zorunlu kılmak için gereklidir. "Birden çok kişiye" yerine "bir" yerine bu "sıfır" değerine dikkat edin.

Şimdi, kardinalitenin "sıfır" (tanımlayıcı olmayan) olabileceği tanımlayıcı olmayan ilişkinin bir örneği, bir varlıktaki bir kayıt / nesnenin -A "kayda" veya "olmayabilir" değerine bir değere sahip olduğunu söylediğimiz durum / s başka bir Varlık-B'de.

A varlığının bir kaydının kendisini diğer Varlık-B kayıtlarına tanımlama olasılığı olduğundan, Varlık-B'de Varlık-B kaydının kimlik değerine sahip bir sütun olmalıdır. Varlık-A'daki hiçbir kayıt, Varlık-B'deki kaydı / kayıtları (veya nesneyi / nesneleri) tanımlamazsa bu sütun "Boş" olabilir.

Nesne Odaklı (gerçek dünya) Paradigmasında, B Sınıfı bir nesnenin varlığı için A Sınıfı nesnesine zorunlu olarak (güçlü bir şekilde bağlı olmadığı), yani B Sınıfı'nın Sınıf Sınıf-A'nın, Sınıf-A nesnesinin aksine, Sınıf-A nesnesini "İçeren" (İçeren) olabileceği şekilde, Sınıf-A nesnesine (Kompozisyon) sahip olması gerekir; B) yaratma.

SQL Query bakış açısından, varlık-B'de, varlık-B için ayrılmış yabancı anahtar için "boş olmayan" tüm kayıtları sorgulayabilirsiniz. Bu, Varlık-A'daki satırlar için belirli bir karşılık gelen değere sahip tüm kayıtları getirir. Alternatif olarak, Null değerine sahip tüm kayıtlar, Varlık-B'de Varlık-A'da kaydı olmayan kayıtlar olur.


-1

Tablolarda var olan olası kardinaliteyi düşünmenin daha iyi olduğunu düşünüyorum. Mümkün olan minimum kardinalite sıfır olabilir. İsteğe bağlı olduğunda, ilgili tablodan tuples minimum katılım sıfır olabilir, Şimdi yabancı anahtar değerlerine izin verilmesine gerek yoktur.

Ama cevap her şey işe bağlı.


-3

Yabancı anahtar fikri, ana tabloda zaten var olan bir değere referans verme kavramına dayanır. Bu yüzden diğer tabloda yabancı anahtar denir. Bu kavrama referans bütünlüğü denir. Yabancı anahtar boş alan olarak bildirilirse, referans bütünlüğünün mantığını ihlal eder. Neye atıfta bulunacak? Yalnızca ana tabloda bulunan bir şeye işaret edebilir. Bu nedenle, yabancı bir anahtar alanı boş olarak bildirmenin yanlış olacağını düşünüyorum.


"Hiçbir şeye" atıfta bulunabilir veya değerini henüz bilmiyorsunuzdur NULL, ancak referans bütünlüğünün söylediği şey, "bir şeye" atıfta bulunması durumunda orada olması gerektiğidir.
yaxe

-7

Bir tablonun yabancı anahtarının diğer bazı tablonun da birincil anahtarı olduğunu düşünüyorum.Bu yüzden null'lara izin vermeyecek.Yani yabancı anahtarda null değerine sahip olma sorunu yok.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.