Değişken varlıkların ilişkisel tabloya nasıl dönüştürüleceğini bilmiyorum


9

GİRİŞ VE İLGİLİ BİLGİLER:

Aşağıdaki örnekte karşılaştığım sorun gösterilmektedir:

Hayvanın bir kedi ya da köpek olabilen bir ırkı vardır . Kedi de olabilir siyam veya Pers . Köpek bir Alman çoban veya Labrador köpeği olabilir .

Hayvan güçlü bir varlık iken, ırkı sunulan iki değerden birine (kedi veya köpek) sahip olabilen bir özelliktir. Her iki değer de karmaşıktır (burada sorunu göstermek için sadece köpek / kedi türünü ekledim, ancak kedinin / köpeğin adı ve diğer şeyler de olabilir).

SORUN:

Bu örnek için ilişkisel tablolar oluşturmak nasıl bilmiyorum.

SORUNU ÇÖZME ÇALIŞMALARIM:

Soruyu temsil eden Chen'in notasyonunu kullanarak ER diyagramı çizmeye çalıştım, ancak bir acemi olarak doğru yaptım mı bilmiyorum. İşte ne var:

resim açıklamasını buraya girin

Yanlış bir şey çizersem özür dilerim, lütfen bu durumda beni düzeltin. Sadece "özgür çözüm" elde etmek istemiyorum, aynı zamanda bu problemle nasıl başa çıkacağımı öğrenmek istiyorum, böylece gelecekte kendi başıma çözebilirim.

Aklıma gelen tek şey, biri kediler için diğeri köpekler için olmak üzere iki ayrı tablo oluşturmak. Ayrıca, Hayvan tablosundaki yarış niteliği yalnızca kedi veya köpek değerini depolardı . Bunun gibi bir şey:

Animal< # Animal_ID, race, other attributes >
Cat < # Cat_ID, $ Animal_ID, breed >
Dog < # Dog_ID, $ Animal_ID, breed >

Çözümüm hakkında gerçekten kötü bir his var ve bunun yanlış olduğundan korkuyorum, dolayısıyla aşağıdaki soru.

SORULAR:

  • Örneğimi ER diyagramına nasıl dönüştürebilirim?
  • Bu ER diyagramını ilişkisel tablolara nasıl dönüştürebilirim?

Daha fazla bilgi gerekiyorsa bir yorum bırakın ve en kısa sürede yazımı güncelleyeceğim. Ayrıca burada oldukça yeni olduğum için uygun etiketleri eklemekten çekinmeyin.

Teşekkür ederim.


1
EER diyagramlarının tablolara dönüştürülmesi TJTeorey, D.Yang, JPFry'nin 1986'dan bu makalesinde bulunabilir: Genişletilmiş Varlık-İlişki Modeli Kullanılarak İlişkisel Veritabanları için Mantıksal Bir Tasarım Metodolojisi . Çok basit ve en sevdiğim makalelerden biri.
miracle173

Yanıtlar:


11

Bu senaryo için uygun yapı bir Alt Sınıf / Kalıtım modelidir ve bu cevapta önerdiğim kavramla hemen hemen aynıdır: Heterojen sıralı değer listesi .

Bu soruda önerilen model, Animalvarlığın tür (yani race) ve tüm türlerde ortak olan özellikleri içermesi bakımından oldukça yakındır . Ancak, gereken iki küçük değişiklik vardır:

  1. Cat_ID ve Dog_ID alanlarını ilgili varlıklarından kaldırın:

    Burada anahtar kavram olmasıdır herşey bir olduğu Animalbakılmaksızın, race: Cat, Dog, Elephant, vb. Başlangıç noktası, herhangi bir göz önüne alındığında raceait Animalgerçekten bu yana ayrı bir tanımlayıcı gerekmez:

    1. Animal_IDbenzersizdir
    2. Cat, Dogve herhangi bir ek racegelecekte eklenen kişiler, kendileri tarafından, tamamen herhangi bir temsil yok Animal; yalnızca ana kuruluşta yer alan bilgilerle birlikte kullanıldığında bir anlamı vardır Animal.

    Dolayısıyla, Animal_IDmülkiyet içinde Cat, Dogvb kişiler PK ve FK geri hem Animalvarlık.

  2. Aşağıdakileri ayırt edin breed:

    İki özelliğin aynı adı paylaşması, adın aynı olması böyle bir ilişkiyi ima etse bile, bu özelliklerin aynı olduğu anlamına gelmez . Bu durumda, gerçekten sahip olduğunuz şey aslında ve ayrı "türler"CatBreedDogBreed

İlk Notlar

  1. SQL, Microsoft SQL Server'a özgüdür (yani T-SQL'dir). Yani, tüm RDBMS'lerde aynı olmadıkları için veri türlerine dikkat edin. Örneğin, kullanıyorum VARCHARama standart ASCII setinin dışında bir şey saklamanız gerekiyorsa, gerçekten kullanmalısınız NVARCHAR.
  2. "Tip" tabloları kimlik alanları ( Race, CatBreedve DogBreed) vardır değil onlar statik arama değerlerdir uygulama sabitleri (yani onlar uygulamanın parçası) olduğu için otomatik artan (T-SQL açısından yani KİMLİĞİNİ) veritabanıdır ve enumC # (veya diğer dillerde) olarak gösterilir. Değerler eklenirse, kontrollü durumlarda eklenir. Uygulama aracılığıyla gelen kullanıcı verileri için otomatik artış alanlarının kullanımını saklıyorum.
  3. Kullandığım adlandırma kuralı, ana sınıf adından sonra alt sınıf adından başlayarak her alt sınıf tablosunu adlandırmaktır. Bu, tabloların düzenlenmesine yardımcı olur ve alt sınıf tablosunun ana varlık tablosuyla ilişkisini açıkça (FK'lere bakmadan) gösterir.
  4. Views ile ilgili not için lütfen sondaki "Son Düzenleme" bölümüne bakın.

"Irk" olarak "Cins" - Spesifik Yaklaşım

Yarışa Özgü Diyagram Olarak Cins
Bu ilk tablo kümesi arama / tür tablolarıdır:

CREATE TABLE Race
(
  RaceID INT NOT NULL PRIMARY KEY
  RaceName VARCHAR(50) NOT NULL
);

CREATE TABLE CatBreed
(
  CatBreedID INT NOT NULL PRIMARY KEY,
  BreedName VARCHAR(50),
  CatBreedAttribute1 INT,
  CatBreedAttribute2 VARCHAR(10)
  -- other "CatBreed"-specific properties as needed
);

CREATE TABLE DogBreed
(
  DogBreedID INT NOT NULL PRIMARY KEY,
  BreedName VARCHAR(50),
  DogBreedAttribute1 TINYINT
  -- other "DogBreed"-specific properties as needed
);

Bu ikinci liste ana "Hayvan" varlığıdır:

CREATE TABLE Animal
(
  AnimalID INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
  RaceID INT NOT NULL, -- FK to Race
  Name VARCHAR(50)
  -- other "Animal" properties that are shared across "Race" types
);

ALTER TABLE Animal
  ADD CONSTRAINT [FK_Animal_Race]
  FOREIGN KEY (RaceID)
  REFERENCES Race (RaceID);

Tablolar bu üçüncü seti her tanımını tamamlamak ücretsiz alt sınıf varlıklardır Racearasında Animal:

CREATE TABLE AnimalCat
(
  AnimalID INT NOT NULL PRIMARY KEY, -- FK to Animal
  CatBreedID INT NOT NULL, -- FK to CatBreed
  HairColor VARCHAR(50) NOT NULL
  -- other "Cat"-specific properties as needed
);

ALTER TABLE AnimalCat
  ADD CONSTRAINT [FK_AnimalCat_CatBreed]
  FOREIGN KEY (CatBreedID)
  REFERENCES CatBreed (CatBreedID);

ALTER TABLE AnimalCat
  ADD CONSTRAINT [FK_AnimalCat_Animal]
  FOREIGN KEY (AnimalID)
  REFERENCES Animal (AnimalID);


CREATE TABLE AnimalDog
(
  AnimalID INT NOT NULL PRIMARY KEY, -- FK to Animal
  DogBreedID INT NOT NULL, -- FK to DogBreed
  HairColor VARCHAR(50) NOT NULL
  -- other "Dog"-specific properties as needed
);

ALTER TABLE AnimalDog
  ADD CONSTRAINT [FK_AnimalDog_DogBreed]
  FOREIGN KEY (DogBreedID)
  REFERENCES DogBreed (DogBreedID);

ALTER TABLE AnimalDog
  ADD CONSTRAINT [FK_AnimalDog_Animal]
  FOREIGN KEY (AnimalID)
  REFERENCES Animal (AnimalID);

Paylaşılan bir breedtür kullanan model "Ek Notlar" bölümünden sonra gösterilir.

ek Notlar

  1. Kavramı, breedkarışıklık için bir odak noktası gibi görünmektedir. Farklı sorular arasında breedpaylaşılan bir özellik olan jcolebrand (soru üzerine bir yorumda) önerildi raceve diğer iki cevap, modellerinde olduğu gibi entegre edildi. Ancak bu bir hatadır, çünkü için değerler breedfarklı değerlerinde paylaşılmaz race. Evet, önerilen diğer iki modelin racebir ebeveyn yaparak bu sorunu çözmeye çalıştığının farkındayım breed. Bu, teknik olarak ilişki sorununu çözerken, ortak olmayan özellikler hakkında ne yapılması gerektiği veya racesahip olmayan bir şeyin nasıl ele alınacağıyla ilgili genel modelleme sorununun çözülmesine yardımcı olmaz breed. Ancak, böyle bir mülkün tümünde varlığının garanti edilmesi durumundaAnimals, bunun için de bir seçenek ekleyeceğim (aşağıda).
  2. Vijayp ve DavidN (aynı gibi görünüyor) tarafından önerilen modeller çalışmıyor çünkü:
    1. Onlar da
      1. ortak olmayan mülklerin depolanmasına izin vermeyin (en azından herhangi bir örnek için ayrı ayrı Animal) veya
      2. tüm races için tüm özelliklerin, Animalbu verileri temsil etmenin çok düz (ve neredeyse ilişkisel olmayan) bir yol olan varlıkta depolanmasını gerektirir . Evet, insanlar bunu her zaman yaparlar, ancak bu, belirli bir alan için tasarlanmamış özellikler için satır başına birçok NULL alana sahip olmak anlamına gelir raceVE satır başına hangi alanların belirli bir racekayıtla ilişkili olduğunu bilmek .
    2. Onlar eklemek için izin vermez raceait Animalyoktur gelecekte breedbir özellik olarak. Ve TÜM bile Animaller bir var breed, yani nedeniyle daha önce hakkında kaydedilmiştir ne yapısını değiştirmek olmaz breed: breedbağlıdır race(yani breediçin Cataynı şey değildir breediçin Dog).

Ortak- / Paylaşılan- Mülkiyet Yaklaşımı olarak "Cins"

resim açıklamasını buraya girin
Lütfen aklınızda bulundurun:

  1. Aşağıdaki SQL, yukarıda sunulan modelle aynı veritabanında çalıştırılabilir:

    1. RaceTablo aynıdır
    2. BreedMasa yenidir
    3. Üç Animaltabloya bir tablo eklenmiştir.2
  2. BreedŞimdi ortak bir mülk olsa bile Race, ana / ana kuruluşta not etmemek doğru görünmemektedir (teknik olarak ilişkisel olarak doğru olsa bile). Yani, hem RaceIDve BreedIDtemsil edilir Animal2. Farklı bir için RaceIDbelirtilen Animal2ve a arasında bir uyumsuzluğu önlemek BreedIDiçin RaceID, her ikisi RaceID, BreedIDde Breedtablodaki bu alanların BENZERSİZ BİR KABUL referans veren bir FK ekledim . Genellikle bir FK'yi BENZERSİZ BİR KISITLAMAYA işaret etmeyi hor görürüm, ancak işte bunun birkaç geçerli nedeninden biri. BENZERSİZ BİR KISIT mantıksal olarak bu kullanım için geçerli kılan bir "Alternatif Anahtar" dır. Lütfen Breedtablonun hala üzerinde bir PK olduğunu unutmayın BreedID.
    1. Birleştirilmiş alanlarda sadece PK ile gitmemenizin ve BENZERSİZ BİR KISITLAMANIN olmamasının sebebi, bunun BreedIDfarklı değerlerde tekrarlanmasına izin vermesidir RaceID.
    2. Hangi PK ve UNIQUE CONSTRAINT'in değiştirilmemesinin sebebi, bunun tek kullanımı olmayabilir BreedID, bu nedenle Breed, RaceIDkullanılabilir olmadan belirli bir değere başvurmak mümkün olmalıdır .
  3. Aşağıdaki model çalışırken, paylaşılan kavramı ile ilgili iki potansiyel kusuru vardır Breed(ve neden Race-özel Breedtabloları tercih ederim ).
    1. TÜM değerlerinin Breedaynı özelliklere sahip olduğuna dair örtük bir varsayım vardır . Bu modelde Dog"ırklar" ve Elephant"ırklar" arasında farklı özelliklere sahip olmanın kolay bir yolu yoktur . Ancak, yine de "Son Düzenleme" bölümünde belirtilen bir yol vardır.
    2. BreedBirden fazla yarışı paylaşmanın bir yolu yoktur . Bunun istenip istenmediğinden emin değilim (ya da belki hayvan kavramında değil, muhtemelen bu tür bir modeli kullanacak başka durumlarda), ama burada mümkün değil.
CREATE TABLE Race
(
  RaceID INT NOT NULL PRIMARY KEY,
  RaceName VARCHAR(50) NOT NULL
);

CREATE TABLE Breed
(
  BreedID INT NOT NULL PRIMARY KEY,
  RaceID INT NOT NULL, -- FK to Race
  BreedName VARCHAR(50)
);

ALTER TABLE Breed
  ADD CONSTRAINT [UQ_Breed]
  UNIQUE (RaceID, BreedID);

ALTER TABLE Breed
  ADD CONSTRAINT [FK_Breed_Race]
  FOREIGN KEY (RaceID)
  REFERENCES Race (RaceID);

CREATE TABLE Animal2
(
  AnimalID INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
  RaceID INT NOT NULL, -- FK to Race, FK to Breed
  BreedID INT NOT NULL, -- FK to Breed
  Name VARCHAR(50)
  -- other properties common to all "Animal" types
);

ALTER TABLE Animal2
  ADD CONSTRAINT [FK_Animal2_Race]
  FOREIGN KEY (RaceID)
  REFERENCES Race (RaceID);

-- This FK points to the UNIQUE CONSTRAINT on Breed, _not_ to the PK!
ALTER TABLE Animal2
  ADD CONSTRAINT [FK_Animal2_Breed]
  FOREIGN KEY (RaceID, BreedID)
  REFERENCES Breed (RaceID, BreedID);


CREATE TABLE AnimalCat2
(
  AnimalID INT NOT NULL PRIMARY KEY, -- FK to Animal
  HairColor VARCHAR(50) NOT NULL
);

ALTER TABLE AnimalCat2
  ADD CONSTRAINT [FK_AnimalCat2_Animal2]
  FOREIGN KEY (AnimalID)
  REFERENCES Animal2 (AnimalID);

CREATE TABLE AnimalDog2
(
  AnimalID INT NOT NULL PRIMARY KEY,
  HairColor VARCHAR(50) NOT NULL
);

ALTER TABLE AnimalDog2
  ADD CONSTRAINT [FK_AnimalDog2_Animal2]
  FOREIGN KEY (AnimalID)
  REFERENCES Animal2 (AnimalID);


Son Düzenleme (umarım ;-)

  1. Türleri arasındaki farklı özelliklere taşıma olasılığı (ve daha sonra güçlük) ile ilgili olarak Breed, ise aynı alt / devralma kavramı fakat kullanılması mümkündür Breedana birim olarak. Bu kurulumda, Breedtablo tüm türler Breed( Animaltablo gibi) için ortak özelliklere sahip RaceIDolacak ve türünü gösterecektir Breed( Animaltabloda olduğu gibi). Sonra gibi alt sınıf tablolar olurdu BreedCat, BreedDogvb. Daha küçük projeler için bu , "aşırı mühendislik" olarak düşünülebilir, ancak bundan faydalanabilecek durumlar için bir seçenek olarak belirtilmektedir.
  2. Her iki yaklaşım için de bazen Görünümleri tam varlıklar için kısayollar olarak oluşturmaya yardımcı olur. Örneğin:

    CREATE VIEW Cats AS
       SELECT  an.AnimalID,
               an.RaceID,
               an.Name,
               -- other "Animal" properties that are shared across "Race" types
               cat.CatBreedID,
               cat.HairColor
               -- other "Cat"-specific properties as needed
       FROM    Animal an
       INNER JOIN  AnimalCat cat
               ON  cat.AnimalID = an.AnimalID
       -- maybe add in JOIN(s) and field(s) for "Race" and/or "Breed"
    
  3. Mantıksal varlıkların bir parçası olmasa da, en azından kayıtların ne zaman eklendiğini ve güncellendiğini anlamak için tablolarda denetim alanlarının olması oldukça yaygındır. Yani pratik açıdan:
    1. Tabloya bir CreatedDatealan eklenir Animal. AnimalCatHer iki tablo için eklenen satırların bir işlem içinde aynı anda yapılması gerektiğinden , bu alan alt sınıf tablolarının hiçbirinde (örneğin ) gerekli değildir .
    2. Tabloya ve tüm alt sınıf tablolarına bir LastModifiedDatealan eklenir Animal. Bu alan yalnızca söz konusu tablo güncellenirse güncellenir: bir güncelleme gerçekleşir AnimalCatancak Animalbelirli bir tarih için girilmezse AnimalID, yalnızca LastModifiedDatealan AnimalCatseçilir.

2
Her nasılsa problemimin tam olarak ne olduğunu anladığını hissediyorum. Bağlantılı cevabınıza bir göz atacağım ve dikkatlice çalışacağım. Sadece basit bir tablo tanımı da harika olurdu (SQL sorguları şu anda yazmak için çok fazla ise). Yayınınızı SQL sorguları veya tablo tanımlarıyla güncellemeye karar verirseniz, lütfen bana bir yorum bırakın. Tekrar teşekkürler. Saygılarımla.
AlwaysLearningNewStuff

1
Cevabınızı gerçek hayat durumuma uygulamaya çalışıyorum. Talimatlarınızı körü körüne uygularsam, tasarımımı daha da optimize etme fırsatını kaçırabileceğime inanıyorum. Sorularımı mükemmel bir şekilde anlayabildiğiniz ve mükemmel cevaplar verebildiğiniz için en son soruma göz atmanızı istiyorum. Gelecekte okuyanlar için de faydalı olacak şekilde genel veri modelini kullanma sorusunu oluşturdum. Eğer bulmakta sorun yaşıyorsanız bana bir yorum bırakın. Rahatsız ettiğin için teşekkürler ve özür dilerim ...
AlwaysLearningNewStuff

@AlwaysLearningNewStuff Merhaba. Bu mesajı daha önce aldım, ancak hemen almak için zamanım yoktu. Yukarıdaki adınızı tıklayarak yeni soruyu bulabildim ve tüm sorularınızı gösterir :-).
Solomon Rutzky

Bu soruya değiniyordum . Özetle: Ortak özelliklere sahip 3 birimim var D, bu yüzden cevabınızdan yöntem uygulamak istedim. İki kuruluşun, Eüçüncü kuruluşta bulunmayan ortak bir özelliği vardır. Bu gerçeği görmezden gelmeli ve standart çözüm mü uygulamalıyım yoksa tasarımımı daha da optimize etmenin bir yolu var mı?
AlwaysLearningNewStuff

4

Öncelikle, ER modelleme ve ilişkisel modelleme arasında ayrım yapmak için iyi gidiyorsunuz. Birçok yeni başlayan yok.

Web'deki yararlı makaleleri aramak için kullanabileceğiniz bazı kelimeler.

Durumunuz klasik bir sınıf / alt sınıf örneğidir veya isterseniz / subtype yazın.

ER modellemesinde kullanılan ifade "genelleme / uzmanlaşma" dır. Ve makalelerin çoğu bunu EER (Gelişmiş Varlık-İlişki) modellemesi adı verilen bir şey altında gösteriyor. Bu Peter Chen'in ER modellemesinin orijinal sunumunda değildi. Daha sonra eklendi. Pdf biçiminde gen / spec'in oldukça iyi bir özeti için buraya tıklayın

Ardından, bir sınıf / alt sınıf durumunu ilişkisel modellemeye dönüştürürken tablolar tasarlarsınız. Birden fazla yaklaşım var. İki ana yaklaşıma tek tablo kalıtım ve sınıf tablo kalıtım denir. Her birinin avantajları ve dezavantajları vardır. Bu iki tasarımın en iyi sunumu Martin Fowler'ten geliyor. Ana hatlarını burada ve burada görebilirsiniz .

Tek tablo kalıtımının en büyük avantajı basitliktir. Her şey tek bir tabloda saklanıyor. En büyük dezavantajı bir sürü NULLS. Bu yer ve zaman kaybına neden olabilir ve kafa karıştırıcı mantığa neden olabilir.

Sınıf tablosu mirası birleştirme gerektirir, ancak bunlar basit ve hızlıdır. Özellikle, alt sınıf tablolarındaki PK'nın üst sınıf tablodaki PK'nın bir kopyası olduğu, paylaşılan birincil anahtar adı verilen bir teknik kullanıyorsanız. Üst sınıf verilerle üst sınıf verileri birleştiren her alt sınıf için görünümler oluşturabilirsiniz.

Son olarak, bu alanda sizinki gibi soruları toplayan bir etiket var.
İşte burada:


1
+1 Beni şaşırtan şey, tablo diyagramlarında birincil anahtarların olmamasıdır. Özellikle "classTableInheritance" içinde tüm bu tabloların aynı birincil anahtarla bağlı olduğunu göremiyorum.
miracle173

@ miracle173 geçerli bir nokta. Nedense, Fowler diyagramlara PK'ları ve FK'ları dahil etmiyor. Bu ayrıntıyı sağlayan sınıf tablosu mirası altında başka makaleler de vardır. Sınıf tablosu mirasının tüm uygulamaları, paylaşılan birincil anahtarla birleştirilmez. Bunu öneririm. Ekleme zamanında biraz daha fazla iş, ancak katılma zamanında daha kolay ve daha hızlı.
Walter Mitty

3

Olası tasarımı şu şekilde görüyorum:

tablo Race

RaceId- PK- Int
RaceName - Varchar(50)

tablo Breed

BreedId - PK- Int
RaceId - FK - Int
BreedName - varchar(50)

tablo Animal

AnimalId - PK- Int
BreedId - FK - Int
Other Columns....

Yukarıdaki bu PK'lar otomatik olarak artan sütun olacaktır. AnimalTablodaki diğer sütunlar buna göre adlandırılabilir.

resim açıklamasını buraya girin


Buna ek olarak, hızı artırmak için daha sonraki dizinleri kolaylaştırmak için Hayvan tablosunda Yarış ve Tip (tetikleyiciler olabilir) tuşlarına sahip bir alan eklerdim.
Felipe Alcacibar

0

Mevcut yönteminiz kötü değil. Bununla birlikte, daha sonra daha fazla yarış ekleyecekseniz (kuş, balık, vb.) Sonra her biri için ayrı bir tablo oluşturmak hantal olabilir. Aşağıdaki gibi bir şey tavsiye ederim:

Animal < # Animal_ID, Breed_ID, other attributes >
Breed < # Breed_ID, Race_ID >
Race < # Race_ID >

Anladığım kadarıyla bir cinsin sadece bir ırkı olmalıdır. Böylece cinsi Hayvan masasında saklarsanız, Irk masasına katılarak yarışı belirleyebileceksiniz. Açıkça, Breed ve Race masalarına gerektiği gibi diğer nitelikleri (ad, açıklama vb.) Ekleyin.

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.