2010-04-20 17 views
6
anahtar

Sadece şablon için Cliffs için bir güncelleme, teşekkürler ChaosPandion olarak.Yasal mı? başvuran İki yabancı anahtarlar aynı birincil

Kişi
PersonID Int PK


PersonID Int PK FK
OtherPersonID Int PK FK

VEYA

Kişi
PersonID Int PK


PersonID Int PK FK
FriendId Int PK FK

Arkadaş
FriendId Int PK
OtherPersonID Int FK

++++++ Orijinal Mesaj Aşağıda ++++++

Herkese selam

bir web geliştirici değilim ve yakın zamanda bir şirket ile bir proje başlamıştır. Şu anda, DBA ile site için tasarlanan şemayı hazırlama konusunda çalışıyorum ve birkaç tablodaki tasarım konusunda bir anlaşmazlık yaşadık ve konuyla ilgili bazı görüşler almak istiyorum.

Temel olarak, bir "arkadaş" ağını uygulayacak bir site üzerinde çalışıyoruz. Sitenin tüm kullanıcıları (Kişi kimliği int kimlik PK, vb) ile bir tablo tblUsers içerecektir. Yapmak isteyen pm ne

(NETWORKID int kimlik PK, Owners_PersonID int FK, Friends_PersonID int FK, vs) ile, kullanıcılar arasındaki ilişkilerin tüm tutacaktır ikinci bir tablo tblNetwork, yaratmaktır. Ya da tersine, NetworkID'yi kaldırın ve hem Birincil anahtar olarak hem Owners_PersonID hem de Friends_PersonID payının paylaşılmasını sağlayın. DBA onun sorunu sahip olduğu

budur. "Bu tür bir mimariyi sadece bir web sitesi için değil, bir veri ambarı şemasında uygulayacağını ve bunun da web geliştiricilerinin kolay yoldan çıkmaya çalıştığı bir başka örnek olduğunu" söyleyerek.

Şimdi belli ki, onun sözler biraz iltihaplı olduğunu ve bir uygun bir cevap bulmak için bana motive yardımcı olmuştur, ancak daha fazla bu yüzden, ben sadece doğru nasıl yapılacağını bilmek istiyorum. 10 yılı aşkın bir süredir veri tabanları ve programlama geliştirmekteyim, bazı üst düzey zihinlerle çalıştım ve bu tür bir tartışmayı hiç duymadım.

DBA'nın yapmak istediği, hem Owners_PersonId hem de Friends_PersonId öğelerini aynı tabloda depolamak yerine, Friends_PersonId dosyasını depolamak için üçüncü bir tablo tblArkadaşlar oluşturmak ve tblNetwork'in sahip olması (NetworkID int identity PK, Owner_PersonID int) FK, FriendsID int FK (TBLArkadaşlar'den)). Bütün bu tbl'lerin evlerine ev sahipliği yapardı (FriendsID int kimliği PK, Friends_PersonID (Kişilerle ilgili olarak)).

Bana göre, üçüncü tabloyu oluşturmak doğada aşırı bir şeydir ve Friends_PersonID için bir takma ad oluşturmaktan başka bir şey yapmaz ve benim tüm sorgularıma eklememem için eklemem gerekir (gereksiz olarak gördüğüm gibi). Her sorguda birleştirme gerçekleştirmek için gerekli olacak ek döngüleri belirtin.

Ben teknik olarak, isteyen ne mümkündür, ancak en iyi uygulama ile inline olduğunu anlıyoruz

? En iyi uygulama ne olurdu?

Okuduğunuz için teşekkürler, yorumları takdir edin.

Ryan

+2

Sanırım sorunuzda biraz fazla hikayeniz var :) – ChaosPandion

+0

Muhtemelen haklısınız. Bunun üzerine çalışacağım. :) – devRyan

+0

Seçenek 1 bana doğru görünüyor. DBA neden bir veri ambarı ve bir web sitesi için farklı bir yol için bunu yapmasını önerdi? –

cevap

3

bana mantıklı tek şema şudur:

Person 
    PersonID Int PK 

Friend 
    PersonID Int PK FK 
    OtherPersonID Int PK FK 

Yani belki bu güzel temiz sorguyu yürütür FriendList denilen bir prosedür var:

Select Person.* 
From Friend 
    Inner Join Person On Friend.OtherPersonID = Person.PersonID 
Where Friend.PersonID = @PersonID; 

Tüm sütunları seçmeyi kabul etmiyorum.

+0

Peki, arkadaş listesinin sahibini nasıl saklarsınız? – Andomar

+0

@Andomar - Takip ettiğimden emin değilim. – ChaosPandion

+0

Her ağın bir 'Owner_PersonID' vardır. Soruyu doğru anlarsam, DBA ile posterin çözümü arasındaki en önemli fark, bu bilgiyi – Andomar

1

Ne yapmak isteyen, tblNetwork, o (NETWORKID int kimlik PK, Owners_PersonID int FK, Friends_PersonID int ile kullanıcılar arasındaki ilişkilerin tüm tutacaktır bir ikinci bir tablo oluşturmak için FK, vb. Ya tersine, NETWORKID kaldırmak ve Owners_PersonID ve hem Birincil anahtar olarak paylaşılan Friends_PersonID var.

Ben bu herhangi bir sorun görmüyorum. Ve ben NetworkID'un gereksiz olduğunu kabul ediyorum - iki FK, tablonun doğal anahtarıdır ve bu yüzden onları bir ana sebep olarak kullanmalısınız, aksi halde bir vekil tarafından belirli ilişkilere başvurmanız gereken bir performans nedeniniz yoksa ID (ki bu durumda sahip değilsiniz).

0

Ben sizin tarzınızı söyleyin. Üçüncü masaya sahip olmak, programlama bölümünü daha çok acı çekiyor. Seni doğru anladıysam

7

, Sen öneriyorsun:

Person    PersonID PK 
FriendList   FriendListID, OwnerID, PersonID 

DBA önermektedir:

Person    PersonID PK 
FriendList   FriendListID, OwnerID 
FriendListEntry  FriendListID, PersonID 

Kişisel yaklaşım listesindeki her arkadaş için birden çok satır gerektirecektir. Bu, normal formu ihlal ederek, birden çok kez OwnerID'yi tekrar eder. DBA'nın çözümü, FriendList tablosunda yalnızca FriendListID'e bağlı olan değerlere sahip, daha normalleştirilmiştir.

burada en iyi uygulama DBA iyi arkadaş olmaktır. Onun çözümü ile giderdim çünkü çok önemli değil ve daha sonra ona ihtiyacın var. Network.Owners_PersonID bir ağ için gereksiz yere depolanmaz ise

+0

Üçüncü bir tablonun eklenmesinin şemayı daha normal hale getirdiğini göremiyorum. – ChaosPandion

+0

@ChaosPandion: İki tablo çözümü, ikinci bir normal formu (http://en.wikipedia.org/wiki/Second_normal_form), her bir arkadaşa – Andomar

+0

listesindeki yinelemeyi geçersiz kılar. netleştirmek adına. Düzenleme, yukarıda listelenen tam olarak Andomar gibidir. – devRyan

2

Kişisel tasarım, Third Normal Form ihlal eder.

Ama DBA tasarımı aslında nasıl yardımcı anlamıyorum.Birçok çoğa Users ve Networks arasındaki tablo olması Friends umuyordum:

Users ----<- Friends ->---- Networks 

Ve ayrıca: Bir başka deyişle

CREATE TABLE tblUsers (
    PersonID INT IDENTITY PRIMARY KEY 
); 

CREATE TABLE tblNetworks (
    NetworkID INT IDENTITY PRIMARY KEY, 
    Owner_PersonID INT NOT NULL REFERENCES tblUsers 
); 

CREATE TABLE tblFriends (
    NetworkID INT NOT NULL REFERENCES tblNetworks, 
    FriendID INT NOT NULL REFERENCES tblUsers, 
    PRIMARY KEY(NetworkID, FriendID) 
); 

, basit birçok çoğa bir ilişki var , Networks başvuruları, yalnızca belirtilen ağın sahibini tanımlamak için Users referans numarasıdır. Bu şekilde, belirli bir ağ için yalnızca bir satır vardır, bu nedenle bazı satırlardaki ağ sahibini değiştirerek bir güncelleme anormalliği oluşturamazsınız.

Bu, varlıkları çok fazla ayrı tablolara bölündüğünü sanmıyorum. Hala belirli bir ağ için arkadaş listesini alabilirsiniz:

SELECT ... FROM Networks n JOIN Friends f ON (n.NetworkID=f.NetworkID) 

Bu yolu (? parametre için verilen kullanıcının kimliği geçmesi) tüm ağlardan bir kullanıcının bütün arkadaşları alabilirsiniz:

SELECT ... FROM Friends u 
JOIN Friends f ON (u.NetworkID=f.NetworkID) 
WHERE u.UserID = ? 

SELECT ... FROM Networks u 
JOIN Networks f ON (u.Owner_UserID=f.Owner_UserID) 
WHERE u.FriendID = ? 

Ama avantajı olası güncelleme anomaliyi ortadan kaldırmış olduk olmasıdır: orijinal tasarımda

, hemen hemen aynı.

+0

Bakın, yukarıda sahip olduğunuz şeylerle çalışabilirim. Aslında onu tercih ederim. DBA'nın şemayı sadece “yazdırabilir” olup olmadığını merak ediyor ve kağıt üzerinde neler olduğunu fark etmemekle tartışıyor. – devRyan

+0

Bu veritabanı tasarımı hakkında yüz yüze bir tartışma yaptınız ve bir beyaz tahtada bir şeyler mi çizdiniz? Sadece e-posta ile iletişim kuruyorsanız, bu oldukça verimsiz ve yanlış anlamaya eğilimlidir. –

+0

WebEx üzerinden çalışıyoruz. – devRyan

İlgili konular