इस परिदृश्य के लिए उचित संरचना सबक्लास / इनहेरिटेंस मॉडल है, और इस उत्तर में प्रस्तावित अवधारणा के लगभग समान है: विषम मूल्य की सूची का आदेश दिया ।
इस प्रश्न में प्रस्तावित मॉडल वास्तव में काफी करीब है Animal
जिसमें इकाई में प्रकार (यानी race
) और सभी प्रकार के गुण हैं। हालाँकि, दो छोटे बदलाव की जरूरत है:
अपनी संबंधित संस्थाओं से Cat_ID और Dog_ID फ़ील्ड निकालें:
यहां मुख्य अवधारणा है कि है सब कुछ एक है Animal
, की परवाह किए बिना race
: Cat
, Dog
, Elephant
, और इतने पर। उस शुरुआती बिंदु को देखते हुए, किसी भी विशेष race
को Animal
वास्तव में एक अलग पहचानकर्ता की आवश्यकता नहीं है:
Animal_ID
अद्वितीय है
Cat
, Dog
, और किसी भी अतिरिक्त race
संस्थाओं भविष्य में जोड़ा, स्वयं ही, पूरी तरह से किसी विशेष का प्रतिनिधित्व नहीं करते हैं Animal
; वे केवल, जिसका अर्थ है जब मूल इकाई में निहित जानकारी के साथ संयोजन में उपयोग किया है Animal
।
इसलिए, Animal_ID
में संपत्ति Cat
, Dog
, आदि संस्थाओं दोनों पी और करने के लिए वापस आ गया है FK Animal
इकाई।
के बीच का अंतर breed
:
सिर्फ इसलिए कि दो गुणों का हिस्सा एक ही नाम नहीं है का मतलब जरूरी है कि उन गुणों ही कर रहे हैं, भले ही नाम ही किया जा रहा है का तात्पर्य एक ऐसे रिश्ते। इस मामले में, आपके पास वास्तव में क्या है CatBreed
और DogBreed
अलग प्रकार के "प्रकार" के रूप में
प्रारंभिक नोट्स
- SQL Microsoft SQL सर्वर (यानी T-SQL) के लिए विशिष्ट है। मतलब, डेटाटाइप्स के बारे में सावधान रहें क्योंकि वे सभी आरडीबीएमएस के समान नहीं हैं। उदाहरण के लिए, मैं उपयोग कर रहा हूं
VARCHAR
लेकिन अगर आपको मानक ASCII सेट के बाहर कुछ भी स्टोर करने की आवश्यकता है, तो आपको वास्तव में उपयोग करना चाहिए NVARCHAR
।
- "प्रकार" तालिकाओं के आईडी क्षेत्रों (
Race
, CatBreed
, और DogBreed
) कर रहे हैं नहीं , क्योंकि वे आवेदन स्थिरांक (यानी वे आवेदन का हिस्सा हैं) है कि में स्थिर देखने मान रहे हैं ऑटो incrementing (T-SQL के मामले में यानी पहचान) डेटाबेस और enum
C # (या अन्य भाषाओं) में दर्शाया गया है। यदि मान जोड़े जाते हैं, तो उन्हें नियंत्रित स्थितियों में जोड़ा जाता है। मैं एप्लिकेशन के माध्यम से आने वाले उपयोगकर्ता डेटा के लिए ऑटो-इन्क्रीमेंट फ़ील्ड का उपयोग आरक्षित करता हूं।
- मेरे द्वारा उपयोग किया जाने वाला नामकरण सम्मेलन मुख्य वर्ग के नाम से शुरू होने वाले प्रत्येक उपवर्ग तालिका का नाम है, उपवर्ग नाम के बाद। यह तालिकाओं को व्यवस्थित करने में मदद करता है और साथ ही स्पष्ट रूप से इंगित करता है (FK को देखे बिना) मुख्य इकाई तालिका में उपवर्ग तालिका का संबंध।
- कृपया दृश्य के संबंध में एक नोट के लिए अंत में "फाइनल एडिट" अनुभाग देखें।
"नस्ल" को "रेस" के रूप में -विशिष्ट दृष्टिकोण
तालिकाओं का यह पहला सेट लुकअप / प्रकार तालिकाएँ हैं:
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
);
यह दूसरी सूची मुख्य "पशु" इकाई है:
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);
तालिकाओं का यह तीसरा सेट मानार्थ उप-वर्ग इकाइयाँ हैं जो प्रत्येक Race
की परिभाषा को पूरा करती हैं 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);
साझा breed
प्रकार का उपयोग करने वाला मॉडल "अतिरिक्त नोट्स" अनुभाग के बाद दिखाया गया है।
अतिरिक्त नोट्स
- की अवधारणा
breed
भ्रम के लिए एक केंद्र बिन्दु हो रहा है। यह jcolebrand (प्रश्न पर एक टिप्पणी में) द्वारा सुझाया गया था जो कि breed
विभिन्न race
एस में साझा की गई संपत्ति है , और अन्य दो उत्तरों ने इसे अपने मॉडलों में इस तरह एकीकृत किया है। हालांकि, यह एक गलती है, क्योंकि breed
विभिन्न मूल्यों के लिए साझा नहीं किए गए हैं race
। हां, मैं इस बात से अवगत हूं कि दो अन्य प्रस्तावित मॉडल इस मुद्दे को हल करने का प्रयास करते race
हैं breed
। जबकि यह तकनीकी रूप से रिश्ते के मुद्दे को हल करता है, यह गैर-सामान्य गुणों के बारे में क्या करना है, के समग्र मॉडलिंग प्रश्न को हल करने में मदद नहीं करता है, और न ही इसे कैसे संभालना race
है breed
। लेकिन, इस मामले में कि इस तरह की संपत्ति को सभी में मौजूद होने की गारंटी दी गई थीAnimal
s, मैं इसके लिए एक विकल्प (नीचे) भी शामिल करूंगा।
- Vijayp और DavidN द्वारा प्रस्तावित मॉडल (जो समान प्रतीत होते हैं) इसलिए काम नहीं करते हैं:
- वे या तो
- गैर-सामान्य गुणों को संग्रहीत करने की अनुमति न दें (कम से कम किसी व्यक्ति के व्यक्तिगत उदाहरणों के लिए नहीं
Animal
), या
- आवश्यकता है कि सभी संपत्तियों के लिए सभी संपत्तियों
race
को उस Animal
इकाई में संग्रहीत किया जाए जो इस डेटा का प्रतिनिधित्व करने का एक बहुत ही सपाट (और लगभग गैर-संबंधपरक) तरीका है। हां, लोग ऐसा हर समय करते हैं, लेकिन इसका मतलब है कि उन विशेष गुणों के लिए प्रति पंक्ति कई NULL फ़ील्ड्स हैं race
जो उस विशेष के लिए नहीं हैं और यह जानने के लिए कि प्रति पंक्ति के कौन से फ़ील्ड race
उस रिकॉर्ड के विशेष से संबद्ध हैं ।
- वे एक जोड़ने के लिए अनुमति नहीं देते
race
के Animal
भविष्य नहीं है कि में breed
एक संपत्ति के रूप में। और सभी, भले ही Animal
एक है breed
, कि क्या पहले से के बारे में उल्लेख किया गया है की वजह से संरचना को बदल नहीं होगा breed
कि: breed
पर निर्भर है race
(यानी breed
के लिए Cat
एक ही चीज़ नहीं है breed
के लिए Dog
)।
"नस्ल" के रूप में आम- / साझा- संपत्ति दृष्टिकोण
कृपया ध्यान दें:
नीचे दिए गए मॉडल के रूप में SQL को उसी डेटाबेस में चलाया जा सकता है:
Race
तालिका में एक ही है
Breed
तालिका नया है
- तीन
Animal
तालिकाओं के साथ संलग्न किया गया है2
- यहां तक कि
Breed
अब एक सामान्य संपत्ति होने के बावजूद , यह Race
मुख्य / मूल इकाई में उल्लेखित नहीं है (भले ही यह तकनीकी रूप से सही हो) नहीं लगता है। तो, दोनों RaceID
और BreedID
में प्रतिनिधित्व कर रहे हैं Animal2
। RaceID
विख्यात के बीच एक बेमेल को रोकने के लिए Animal2
और BreedID
यह एक अलग के लिए है RaceID
, मैंने दोनों पर एक एफके जोड़ा है RaceID, BreedID
जो Breed
तालिका में उन क्षेत्रों के एक संदर्भ को संदर्भित करता है। मैं आमतौर पर एक UNIQUE CONSTRAINT को FK की ओर इशारा करते हुए घृणा करता हूं, लेकिन ऐसा करने के लिए कुछ वैध कारणों में से एक है। UNIQUE CONSTRAINT तार्किक रूप से एक "वैकल्पिक कुंजी" है, जो इसे इस उपयोग के लिए वैध बनाती है। कृपया यह भी ध्यान दें कि Breed
टेबल पर अभी भी पीके है BreedID
।
- संयुक्त क्षेत्रों और किसी भी संकलक पर केवल एक पीके के साथ नहीं जाने का कारण यह है कि यह उसी के
BreedID
लिए अलग-अलग मूल्यों को दोहराया जाएगा RaceID
।
- स्विच करने का कारण जो कि PK और UNIQUE CONSTRAINT के आसपास नहीं है, यह केवल इसका उपयोग नहीं हो सकता है
BreedID
, इसलिए यह अभी भी उपलब्ध Breed
होने के बिना एक विशिष्ट मूल्य को संदर्भित करना संभव RaceID
है।
- जबकि निम्नलिखित मॉडल काम करता है, इसमें एक साझा की अवधारणा के संबंध में दो संभावित खामियां
Breed
हैं (और यही कारण है कि मैं Race
-स्पेशल Breed
टेबल पसंद करता हूं )।
- एक निहित धारणा है कि सभी मूल्यों में
Breed
समान गुण हैं। इस मॉडल में Dog
"नस्लों" और Elephant
"नस्लों" के बीच असमान गुण होने का कोई आसान तरीका नहीं है । हालांकि, अभी भी ऐसा करने का एक तरीका है, जिसे "फाइनल एडिट" सेक्शन में नोट किया गया है।
- एक
Breed
से अधिक दौड़ को साझा करने का कोई तरीका नहीं है । मुझे यकीन नहीं है कि अगर ऐसा करना वांछनीय है (या शायद जानवरों की अवधारणा में नहीं, लेकिन संभवतः अन्य स्थितियों में जो इस प्रकार के मॉडल का उपयोग कर रहे हैं), लेकिन यह यहां संभव नहीं है।
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);
अंतिम संपादन (उम्मीद है ;-)
- प्रकारों के बीच असमान गुणों को संभालने की संभावना (और फिर कठिनाई) के संबंध में
Breed
, यह एक ही उपवर्ग / विरासत अवधारणा को रोजगार देना संभव है , लेकिन Breed
मुख्य इकाई के रूप में। इस सेटअप में Breed
तालिका में सभी प्रकार के Breed
(जैसे कि Animal
तालिका) के गुण सामान्य RaceID
होंगे और Breed
यह उसी प्रकार का प्रतिनिधित्व करेगा (जैसा वह Animal
तालिका में करता है )। तो फिर तुम जैसे उपवर्ग तालिकाओं के लिए होता है BreedCat
, BreedDog
, और इतने पर। छोटी परियोजनाओं के लिए इसे "ओवर-इंजीनियरिंग" माना जा सकता है, लेकिन इसे उन स्थितियों के लिए एक विकल्प के रूप में उल्लेख किया जा रहा है, जो इससे लाभान्वित होंगी।
दोनों दृष्टिकोणों के लिए, यह कभी-कभी पूर्ण इकाइयों के लिए शॉर्ट-कट के रूप में दृश्य बनाने में मदद करता है। उदाहरण के लिए, विचार करें:
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"
- तार्किक संस्थाओं का हिस्सा नहीं होने के बावजूद, तालिकाओं में ऑडिट फ़ील्ड रखना काफी सामान्य है, जब रिकॉर्ड डाला और अपडेट किया जा रहा हो, तो कम से कम यह महसूस करें। तो व्यावहारिक रूप में:
- तालिका में एक
CreatedDate
फ़ील्ड जोड़ा जाएगा Animal
। किसी भी उपवर्ग तालिकाओं (जैसे AnimalCat
) में इस क्षेत्र की आवश्यकता नहीं है क्योंकि दोनों तालिकाओं के लिए डाली जा रही पंक्तियों को एक ही समय में लेनदेन के भीतर किया जाना चाहिए।
- एक
LastModifiedDate
फ़ील्ड को Animal
तालिका और सभी उपवर्ग तालिकाओं में जोड़ा जाएगा । यह फ़ील्ड केवल तभी अपडेट की जाती है जब उस विशेष तालिका को अपडेट किया जाता है: यदि कोई अपडेट होता है, AnimalCat
लेकिन Animal
किसी विशेष के लिए नहीं है AnimalID
, तो केवल LastModifiedDate
फ़ील्ड AnimalCat
सेट की जाएगी।