Birden çok tablodaki birincil anahtarlara atıfta bulunan yabancı anahtar?


92

Veritabanı çalışanları altında çalışanların_ce ve çalışanlar_sn olmak üzere iki tablom var.

Her ikisinin de kendi benzersiz birincil anahtar sütunları vardır.

Detuctions adında başka bir tablom var, yabancı anahtar sütununda staff_ce'nin ve staff_sn'nin birincil anahtarlarına başvurmak istiyorum. Mümkün mü?

Örneğin

employees_ce
--------------
empid   name
khce1   prince

employees_sn
----------------
empid   name
khsn1   princess

bu mümkün mü?

deductions
--------------
id      name
khce1   gold
khsn1   silver

Yanıtlar:


100

Senaryonuzu doğru anladığımı varsayarsak, bunu yapmanın doğru yolu budur:

Veritabanınızın daha üst düzey bir tanımından başlayın! Çalışanlarınız var ve çalışanlar "ce" çalışanları ve "sn" çalışanları olabilir (bunlar ne olursa olsun). Nesneye yönelik terimlerle, "ce çalışanı" ve "sn çalışanı" olarak adlandırılan iki alt sınıfı olan bir "çalışan" sınıfı vardır.

Sonra üç tablolara bu üst düzey açıklamasını çevirmek: employees, employees_ceve employees_sn:

  • employees(id, name)
  • employees_ce(id, ce-specific stuff)
  • employees_sn(id, sn-specific stuff)

Tüm çalışanlar çalışan olduğundan (ha!), Her çalışanın employeesmasada bir sırası olacaktır . "ce" çalışanlarının da employees_cemasada bir sırası vardır ve "sn" çalışanlarının da employees_snmasada bir sırası vardır . employees_ce.idBir yabancı anahtardır employees.idgibi, employees_sn.idolduğunu.

Herhangi bir türden (ce veya sn) bir çalışana atıfta bulunmak için employeestabloya bakın . Yani, sorun yaşadığınız yabancı anahtar bu tabloya başvurmalıdır!


17
CE ve sn'yi nasıl karşılıklı olarak dışlarsınız? Bir çalışan aynı anda ce ve sn olamayacağından, bunu veri tabanına yansıtmak iyi bir uygulama olacaktır. Şu anda bu sorunu yaşıyorum.
Rolf

Sanırım birden fazla sütun anahtarı önceki yorumumdaki soruna yardımcı olabilir ... şu anda bunu araştırıyorum.
Rolf

12
Temel tabloda ve türetilmiş tablolarda bir tür depolayarak çalışanı yalnızca bir tabloda (ve doğru olanı) olmaya zorlayabilirsiniz. Birincil anahtar kimliğini, benzersiz bir anahtarı açık (kimlik, tür) yapın, alt tabloların yabancı anahtarını açık (kimlik, tür) yapın ve yalnızca doğru türe sahip olmak için her alt tabloya bir KONTROL kısıtlaması koyun. Veya, eğer veri tabanınız küresel kontrol kısıtlamaları yapıyorsa (ve çok büyük hız cezası olmadan), elbette sadece MEVCUT DEĞİL kontrolü yapabilirsiniz.
derobert

Tam açıklama ve uygulama ayrıntıları için bu Yanıtı kontrol edin .
PerformanceDBA

belirli bir kimliği olan bir çalışanın 'se' veya 'sn' olduğunu nasıl anlarım?
mhrsalehi

22

Muhtemelen iki yabancı anahtar kısıtlaması ekleyebilirsiniz (dürüst olmak gerekirse: Bunu hiç denemedim), ancak bu, her iki tabloda da ana satırın var olduğu konusunda ısrar eder.

Bunun yerine, muhtemelen iki çalışan alt türünüz için bir süper tür oluşturmak ve ardından yabancı anahtarı oraya işaret etmek istersiniz. (Elbette iki tür çalışanı bölmek için iyi bir nedeniniz olduğunu varsayarsak).

                 employee       
employees_ce     ————————       employees_sn
————————————     type           ————————————
empid —————————> empid <——————— empid
name               /|\          name
                    |  
                    |  
      deductions    |  
      ——————————    |  
      empid ————————+  
      name

type çalışan tablosunda ce veyasn .


Birden fazla yabancı anahtar eklemeyi denedim, çalıştılar ama bir kayıt eklerken java derbisi bana her iki yabancı anahtar kısıtlamasının da ihlal edildiğini söylüyor!

PostgreSQL'de denedim ve orada çalışıyor. Her iki tabloda da ebeveyn kaydınız var mı?
derobert

demek istediğin ebeveyn kaydı, imparatorluk?

Elbette, sorun "kesintiler" tablosundan "çalışan" tablosuna kaydırılmıştır. Bir türe göre potansiyel olarak farklı Varlıklara nasıl referans verirsiniz?
gawpertron

1
@gawpertron: İmparatorluk her türden benzersizdir. Hangi alt tabloya başvurmanız gerektiğini görmek için 'tür' alanını kullanabilirsiniz. Ya da LEFT JOINyeterince az varsa hepsi. 'Çalışan' temel tablosu kullanılmadığında, birincil anahtar bildirilemez (çünkü bu, tabloA'ya veya tablo B'ye veya… 'ye başvuruyor olabilir); şimdi olabilir. Bölme bilgelik employees_ceve employees_snkabul edilmiş ve bu varsayım belirtilmektedir.
derobert

20

Aslında bunu kendim yapıyorum. Diğer 3 tablodaki kayıtlar için açıklamalar içeren 'Yorumlar' adlı bir tablom var. Her iki çözüm de aslında muhtemelen istediğiniz her şeyi ele almaz. Senin durumunda şunu yaparsın:

1.Çözüm:

  1. Çalışanlar_ce ve çalışanlar_sn'ye her tabloda farklı bir varsayılan değere sahip küçük bir alan ekleyin (Bu alan bir 'tablo tanımlayıcısını' temsil eder, bu nedenle bunlara tid_ce & tid_sn adını vereceğiz)

  2. Tablonun PK'sini ve tablo kimliği alanını kullanarak her tabloda Benzersiz bir Dizin oluşturun.

  3. Yabancı anahtarın ikinci yarısını (Tablo Kimliği) saklamak için 'Kesintiler' tablonuza küçük bir alan ekleyin

  4. 'Kesintiler' tablonuzda 2 yabancı anahtar oluşturun (Bilgi tutarlılığını uygulayamazsınız çünkü bir anahtar veya diğeri geçerli olacaktır ... ancak ikisi birden asla:

    ALTER TABLE [dbo].[Deductions]  WITH NOCHECK ADD  CONSTRAINT [FK_Deductions_employees_ce] FOREIGN KEY([id], [fk_tid])
    REFERENCES [dbo].[employees_ce] ([empid], [tid])
    NOT FOR REPLICATION 
    GO
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_ce]
    GO
    ALTER TABLE [dbo].[Deductions]  WITH NOCHECK ADD  CONSTRAINT [FK_Deductions_employees_sn] FOREIGN KEY([id], [fk_tid])
    REFERENCES [dbo].[employees_sn] ([empid], [tid])
    NOT FOR REPLICATION 
    GO
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_sn]
    GO
    
    employees_ce
    --------------
    empid    name     tid
    khce1   prince    1
    
    employees_sn
    ----------------
    empid    name     tid 
    khsn1   princess  2
    
    deductions
    ----------------------
    id      tid       name  
    khce1   1         gold
    khsn1   2         silver         
    ** id + tid creates a unique index **
    

Çözüm 2: Bu çözüm, bilgi tutarlılığının korunmasına izin verir: 1. 'Kesintiler' tablosunda ikinci bir yabancı anahtar alanı oluşturun, her iki yabancı anahtarda da Boş değerlere izin verin ve normal yabancı anahtarlar oluşturun:

    employees_ce
    --------------
    empid   name
    khce1   prince 

    employees_sn
    ----------------
    empid   name     
    khsn1   princess 

    deductions
    ----------------------
    idce    idsn      name  
    khce1   *NULL*    gold
    *NULL*  khsn1     silver         

Bütünlük yalnızca sütun boş değilse kontrol edilir, böylece bilgi tutarlılığını koruyabilirsiniz.


6

Bunun uzun süredir durgun bir konu olduğunu biliyorum, ancak burada birileri ararsa, çok masalı yabancı anahtarlarla nasıl başa çıkacağım. Bu teknikle herhangi bir DBA zorunlu kademeli işleminiz yoktur, bu nedenle lütfen DELETEkodunuzla ve benzerleriyle uğraştığınızdan emin olun .

Table 1 Fruit
pk_fruitid, name
1, apple
2, pear

Table 2 Meat
Pk_meatid, name
1, beef
2, chicken

Table 3 Entity's
PK_entityid, anme
1, fruit
2, meat
3, desert

Table 4 Basket (Table using fk_s)
PK_basketid, fk_entityid, pseudo_entityrow
1, 2, 2 (Chicken - entity denotes meat table, pseudokey denotes row in indictaed table)
2, 1, 1 (Apple)
3, 1, 2 (pear)
4, 3, 1 (cheesecake)

SO Op Örneği şuna benzer

deductions
--------------
type    id      name
1      khce1   gold
2      khsn1   silver

types
---------------------
1 employees_ce
2 employees_sn

1

Teknik olarak mümkün. Muhtemelen kesintilerde çalışan_ce ve çalışanlar_sn'ye atıfta bulunursunuz. Ama neden companies_sn ve çalışanlar_ce'yi birleştirmiyorsunuz? İki masanız olması için hiçbir sebep göremiyorum. Pek çok ilişkiye kimse yok. Ve (bu örnekte değil) birçok sütun.

Bir sütun için iki referans yaparsanız, çalışanın her iki tabloda da bir girişi olmalıdır .


1

Evet mümkün. 3. tablo için 2 FK tanımlamanız gerekecektir. Her FK, bir tablonun gerekli alanlarına işaret eder (yani yabancı tablo başına 1 FK).


0

Herhangi bir nedenle iki çalışan türü için iki masanız olması gerektiğini varsayarak, vmarquez'in cevabını genişleteceğim:

Şema:

employees_ce (id, name)
employees_sn (id, name)
deductions (id, parentId, parentType, name)

Kesintilerdeki veriler:

deductions table
id      parentId      parentType      name
1       1             ce              gold
2       1             sn              silver
3       2             sn              wood
...

Bu, kesintilerin şemanızdaki başka herhangi bir tabloyu işaret etmesine izin verir. Bu tür bir ilişki, veritabanı düzeyindeki kısıtlamalar, IIRC tarafından desteklenmez, bu nedenle Uygulamanızın kısıtlamayı doğru bir şekilde yönettiğinden emin olmanız gerekir (bu, aynı veritabanına giren birkaç farklı Uygulamanız / hizmetiniz varsa daha zahmetli hale getirir).

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.