Yabancı anahtarı birincil anahtar olarak kullanmak sorun olur mu?


108

İki masam var:

  • Kullanıcı (kullanıcı adı, şifre)
  • Profil (profil kimliği, cinsiyet, doğum tarihi, ...)

Şu anda bu yaklaşımı kullanıyorum: Her Profil kaydında Kullanıcı tablosuna bağlanan yabancı anahtar olarak "userId" adlı bir alan var . Bir kullanıcı kaydolduğunda Profil kaydı otomatik olarak oluşturulur.

Arkadaşımın önerisiyle kafam karıştı: "userId" alanını yabancı ve birincil anahtar olarak almak ve "profileId" alanını silmek. Hangi yaklaşım daha iyidir?


3
Entity Framework, zeroOrOne (ve bir) -bire ilişkiler için bunu (önce kodla) üretir. Yani ... mümkün. En iyi yol bu mu ... Bu başka bir soru. Ama geçerli. Kendi veritabanımı oluştururken bunu asla yapmadım (ama bunu hiç düşünmedim).
Raphaël Althaus

Yanıtlar:


137

Yabancı anahtarlar hemen hemen her zaman "Yinelemelere İzin Ver" şeklindedir, bu da onları Birincil Anahtarlar olarak uygunsuz hale getirir.

Bunun yerine, tablodaki her kaydı benzersiz şekilde tanımlayan bir alan bulun veya birincil anahtar olarak işlev görmesi için yeni bir alan (otomatik artan tam sayı veya GUID) ekleyin.

Bunun tek istisnası olan tablolardır bire-bir ilişki, yabancı anahtar ve birincil bağlantılı tablonun anahtar bir ve aynıdır.


77
İki yabancı anahtardan oluşan bileşik bir birincil anahtar da çoktan çoğa ilişkileri uygulamak için mükemmeldir.
sağ kat

2
@rezadru: Sağ sayfa ile aynı fikirde olmamaktan uzaktır, ancak vekil anahtar neredeyse her zaman daha iyi bir seçimdir.
Robert Harvey

4
Yabancı anahtarla ilgili hiçbir şey 1'den çoka (veya yazıldığı gibi "kopyalara izin ver") anlamına gelmez. Anahtar kısıtlamalar ve benzersizlik, bir veritabanında iki ayrı kavramdır ve bir dizin eklemek kadar kolayca karıştırılabilir (bu üçüncü ayrı bir kavramdır).
blindguy

Ayrıca @RobertHarvey'e de katılıyorum - vekil anahtarlar da bazı durumlarda daha iyi bir seçim yapar. Örneğin, birincil anahtarı başka bir tablonun parçası olarak kullanılan çoktan çoğa ilişkisini gösteren bir ara tablonuz olabilir. Bir vekil anahtar BULUNMADIĞINDA, Birincil Anahtar olarak işaretlenen tüm yabancı anahtarlar, diğer tablolarınızı şişirecektir. Bununla birlikte, bir vekil anahtarınız VARSA, aktarılan her şey bir anahtardır. Bence daha basit ve verimli.
Pablo Alexis Domínguez Grau

42

Birincil anahtarların her zaman benzersiz olması gerekir; tablo bire çok ilişkiyse yabancı anahtarların benzersiz olmayan değerlere izin vermesi gerekir. Tablo bire çok ilişki ile değil, bire bir ilişki ile bağlanmışsa, birincil anahtar olarak yabancı anahtarı kullanmak tamamen iyidir. Aynı kullanıcı kaydının 1'den fazla ilgili profil kaydına sahip olma olasılığına sahip olmasını istiyorsanız, ayrı bir birincil anahtar kullanın, aksi takdirde sahip olduğunuza bağlı kalın.


11

Evet, yabancı anahtar olan bir birincil anahtara sahip olmak yasaldır. Bu nadir bir yapıdır, ancak şunlar için geçerlidir:

  • 1: 1 ilişki. İki tablo, farklı izinler ve ayrıcalıklar nedeniyle yalnızca tablo düzeyinde geçerli olduğundan tek bir tablo içinde birleştirilemez (2017 itibariyle, böyle bir veritabanı tuhaf olacaktır).

  • 1: 0..1 ilişkisi. Profil, kullanıcı türüne bağlı olarak mevcut olabilir veya olmayabilir.

  • performans bir sorundur ve tasarım bir bölüm olarak işlev görür: profil tablosuna nadiren erişilir, ayrı bir diskte barındırılır veya kullanıcılar tablosuyla karşılaştırıldığında farklı bir parçalama politikasına sahiptir. Altını çizen depolama sütunluysa mantıklı olmaz.


Tablolar sık ​​sık birleştirilseydi, olumsuz bir performans olurdu, bu da normal olarak 1 masanın daha iyi olduğu tavsiyesine yol açar. Bazı durumlarda verilere her zaman ayrı olarak erişilir, birleştirilmez ve 1: 1 ilişkiye sahip iki tabloya sahip olmanın kurumsal faydaları olabilir.
blindguy

4

Bire bir ilişkiye sahip olmak genellikle kötü bir uygulama olarak kabul edilir. Bunun nedeni, verileri tek bir tabloda temsil edip aynı sonucu elde edebilmenizdir.

Ancak, referans yaptığınız tabloda bu değişiklikleri yapamayabileceğiniz durumlar vardır. Bu durumda Yabancı anahtarın birincil anahtar olarak kullanılmasıyla ilgili bir sorun yoktur. Otomatik olarak artan benzersiz birincil anahtardan ve yabancı anahtardan oluşan bir bileşik anahtara sahip olmak yardımcı olabilir.

Şu anda kullanıcıların oturum açabilecekleri ve bir uygulamayla kullanmak için bir kayıt kodu oluşturabilecekleri bir sistem üzerinde çalışıyorum. İçeri girmeyeceğim nedenlerden dolayı, kullanıcılar tablosuna gerekli sütunları ekleyemiyorum. Bu yüzden kod tablosu ile bire bir rotaya gidiyorum.


2
Tüm verilerin ek sütunlarla aynı tabloda bulunmasının birçok avantajı olduğu konusunda size çoğunlukla katılıyorum. Buna rağmen .. "Verileri bir tabloda temsil edebilir ve aynı sonucu elde edebilirsiniz" ..: ayrı bir tabloya sahip olmak yararlı olabilir, örneğin burada profil tablosu girişi isteğe bağlıysa. Örneğin, her banka müşterisinin internet bankacılığı kaydı olmayabilir. Bu durumda IB kayıt tablosu, diğer tabloların başka alt kayıtlara sahip olmasını kısıtlamak için kullanılabilir. Yine burada IB kayıt tablosu için yeni bir PK ile de yapılabilir.
Teddy

1
@Teddy Aynı şekilde söylediklerinize çoğunlukla katılıyorum. Ancak, orijinal soruda "... Profil kaydı otomatik olarak oluşturulur ..." ifadesi, Profil tablosunun isteğe bağlı olmadığını ima eder. Profil tablosunun isteğe bağlı olduğu bir durumda, evet ayrı bir tablo olarak kullanmak mümkündür. Ancak yine aynı tabloda null yapılabilir sütunlar kullanabilirler.
Tshsmith

1
Ayrı bir ikinci tablo kullanarak, yalnızca ikinci tabloya girişi olan kişiler için izin verilen üçüncü bir tabloya girişi engelleyebiliriz.
Teddy

Kesinlikle, ancak 1'e 1 tabloları birleştirirsek, boş değerlere sahip kişilerin üçüncü (teknik olarak şimdi ikinci) tabloya erişmesini engelleyebiliriz. Ancak OP'nin sorduğu soru "... kaydolurken .. ... profil kaydı otomatik olarak oluşturulur ..." satırını içerir, bu gereksiz hale getirilir.
Tshsmith

Bunu göz önünde bulundurmamın birincil nedeni, veri ambarlamada olgu ve boyut tablolarını ayırmanın iyi bir uygulama olmasıdır. Ayrı olgu ve boyut tabloları, PowerPivot, PowerBI ve Tableau gibi yazılımlarla çalışırken yararlı ipuçlarıdır.
Marco Rosas

4

Evet, bu tablolar arasında bire bir ilişki olması durumunda yabancı anahtar birincil anahtar olabilir


2
bu aynı zamanda süper tip-alt tip tasarımı için de kullanışlıdır. Alt tür tabloların birincil anahtarı, üst tür tablosuna yabancı anahtar başvurusu olmalıdır.
axelioo

2

Bunu yapmazdım. Ben tutacak profileIDtablonun birincil anahtarıProfile

Yabancı anahtar, iki tablo arasında yalnızca bir başvuru kısıtlamasıdır

Diğer tablolardan kendisine başvuran herhangi bir yabancı anahtarın hedefi olarak birincil anahtarın gerekli olduğu ileri sürülebilir. Yabancı anahtar, herhangi bir tablodaki bir veya daha fazla sütun kümesidir (tablonun birincil anahtarı bir yana, bir aday anahtar olması gerekmez) ve bazılarının birincil anahtar sütunlarında bulunan değerleri tutabilir. diğer masa. Yani yabancı anahtarla eşleşecek bir birincil anahtara sahip olmamız gerekir. Yoksa yapmalı mıyız? Birincil anahtar / yabancı anahtar çiftindeki birincil anahtarın tek amacı, kesin bir birleştirme sağlamaktır - başvurulan birincil anahtarı tutan "yabancı" tabloya göre bilgi tutarlılığını korumaktır. Bu, yabancı anahtarın başvurduğu değerin her zaman geçerli (veya izin verilirse boş) olmasını sağlar.

http://www.aisintl.com/case/primary_and_foreign_key.html


1
Belki - User.UserID ve Profile.UserID arasında FK kısıtlamasına sahipseniz, Profile.UserID üzerinde bir dizine sahip olmanız şiddetle tavsiye edilir. Neden bunu tablo Profilinde birincil kümelenmiş dizini yapmıyorsunuz, ikinci bir dizinden tasarruf ediyor ve veritabanı motoru için çok fazla gereksiz çalışma yapmıyorsunuz?
Reversed Engineer

1

İşe ve sisteme bağlıdır.

Kullanıcı kimliğiniz benzersizse ve her zaman benzersiz olacaksa, userId'yi birincil anahtarınız olarak kullanabilirsiniz. Ancak sisteminizi genişletmek isterseniz, işleri zorlaştıracaktır. Tablo profiline yabancı anahtar eklemek yerine tablo profiliyle ilişki kurmak için tablo kullanıcısına yabancı anahtar eklemenizi öneririm.


0

Kısa cevap: BAĞIMLI .... Bu özel durumda, sorun olmayabilir. Ancak uzmanlar hemen hemen her seferinde buna karşı tavsiyede bulunacaktır; davanız dahil.

Neden?

Anahtarlar, söz konusu tabloya yabancı olduklarında (başka bir tablodan kaynaklandıklarında) tablolarda nadiren benzersizdir. Örneğin, bir öğe kimliği bir ÖĞE tablosunda benzersiz olabilir, ancak SİPARİŞLER tablosunda olmayabilir, çünkü aynı türden bir öğe büyük olasılıkla başka bir sırada var olacaktır. Benzer şekilde, SİPARİŞLER tablosunda sipariş kimlikleri benzersiz olabilir (olabilir), ancak birden çok satır öğesi içeren bir siparişin var olabileceği ORDER_DETAILS gibi başka bir tabloda olmayabilir ve belirli bir siparişte belirli bir öğeye karşı sorgulama yapmak için ikisinin birleştirilmesi gerekir Bu tablonun PK'si olarak FK (order_id ve item_id).

Ben DB uzmanı değilim, ancak mantıksal olarak PK'nız olarak otomatik oluşturulan bir değere sahip olmayı haklı çıkarabilirseniz, bunu yapardım. Bu pratik değilse, iki (veya belki daha fazla) FK'nin bir araya getirilmesi PK'niz olarak hizmet edebilir. AMA, tek bir FK değerinin PK olarak gerekçelendirilebileceği herhangi bir durum düşünemiyorum.

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.