डेटाबेस में वंशानुक्रम मॉडलिंग के लिए सर्वोत्तम अभ्यास क्या हैं?
व्यापार-नापसंद (उदाहरण के लिए) क्या हैं?
(मैं SQL सर्वर और .NET में सबसे अधिक दिलचस्पी रखता हूं, लेकिन मैं यह भी समझना चाहता हूं कि अन्य प्लेटफॉर्म इस मुद्दे को कैसे संबोधित करते हैं।)
डेटाबेस में वंशानुक्रम मॉडलिंग के लिए सर्वोत्तम अभ्यास क्या हैं?
व्यापार-नापसंद (उदाहरण के लिए) क्या हैं?
(मैं SQL सर्वर और .NET में सबसे अधिक दिलचस्पी रखता हूं, लेकिन मैं यह भी समझना चाहता हूं कि अन्य प्लेटफॉर्म इस मुद्दे को कैसे संबोधित करते हैं।)
जवाबों:
एक डेटाबेस में वंशानुक्रम को मॉडल करने के कई तरीके हैं। जो आप चुनते हैं वह आपकी आवश्यकताओं पर निर्भर करता है। यहाँ कुछ विकल्प दिए गए हैं:
तालिका-प्रति-प्रकार (टीपीटी)
प्रत्येक वर्ग की अपनी तालिका है। बेस क्लास में सभी बेस क्लास एलिमेंट्स होते हैं, और प्रत्येक क्लास जो इससे प्राप्त होती है, उसकी अपनी एक टेबल होती है, जिसमें एक प्राइमरी की होती है जो बेस क्लास टेबल की एक विदेशी चाबी होती है; व्युत्पन्न तालिका के वर्ग में केवल विभिन्न तत्व होते हैं।
उदाहरण के लिए:
class Person {
public int ID;
public string FirstName;
public string LastName;
}
class Employee : Person {
public DateTime StartDate;
}
तालिकाओं में परिणाम होगा:
table Person
------------
int id (PK)
string firstname
string lastname
table Employee
--------------
int id (PK, FK)
datetime startdate
टेबल-प्रति-पदानुक्रम (TPH)
एक एकल तालिका है जो सभी विरासत पदानुक्रम का प्रतिनिधित्व करती है, जिसका अर्थ है कि स्तंभों में से कई शायद विरल होंगे। एक डिस्क्रिमिनेटर कॉलम जोड़ा जाता है जो सिस्टम को बताता है कि यह किस प्रकार की पंक्ति है।
उपरोक्त कक्षाओं को देखते हुए, आप इस तालिका को समाप्त करते हैं:
table Person
------------
int id (PK)
int rowtype (0 = "Person", 1 = "Employee")
string firstname
string lastname
datetime startdate
किसी भी पंक्तियों के लिए जो पंक्ति 0 (व्यक्ति) हैं, प्रारंभ हमेशा शून्य रहेगा।
टेबल-प्रति-कंक्रीट (टीपीसी)
प्रत्येक वर्ग की अपनी पूरी तरह से बनाई गई तालिका होती है, जिसमें किसी भी अन्य तालिकाओं का कोई संदर्भ नहीं होता है।
उपरोक्त कक्षाओं को देखते हुए, आप इन तालिकाओं के साथ समाप्त होते हैं:
table Person
------------
int id (PK)
string firstname
string lastname
table Employee
--------------
int id (PK)
string firstname
string lastname
datetime startdate
उचित डेटाबेस डिज़ाइन उचित ऑब्जेक्ट डिज़ाइन की तरह कुछ भी नहीं है।
यदि आप अपनी वस्तुओं को क्रमबद्ध करने के अलावा किसी अन्य चीज़ के लिए डेटाबेस का उपयोग करने की योजना बना रहे हैं (जैसे कि रिपोर्ट, क्वेरी, बहु-अनुप्रयोग उपयोग, व्यावसायिक बुद्धिमत्ता, आदि) तो मैं किसी भी तरह की साधारण मैपिंग को ऑब्जेक्ट्स से टेबल पर करने की सलाह नहीं देता।
बहुत से लोग एक डेटाबेस तालिका में एक इकाई के रूप में एक पंक्ति के बारे में सोचते हैं (मैंने कई साल उन शर्तों में सोचकर बिताए), लेकिन एक पंक्ति एक इकाई नहीं है। यह एक प्रस्ताव है। एक डेटाबेस संबंध (यानी, तालिका) दुनिया के बारे में कुछ कथन का प्रतिनिधित्व करता है। पंक्ति की उपस्थिति इस तथ्य को इंगित करती है कि यह सच है (और इसके विपरीत, इसकी अनुपस्थिति तथ्य को झूठा इंगित करती है)।
इस समझ के साथ, आप देख सकते हैं कि ऑब्जेक्ट-ओरिएंटेड प्रोग्राम में एक एकल प्रकार एक दर्जन से अधिक विभिन्न संबंधों में संग्रहीत किया जा सकता है। और विभिन्न प्रकार के (वंशानुक्रम, संघ, एकत्रीकरण या पूरी तरह से असम्बद्ध द्वारा एकजुट) को आंशिक रूप से एकल संबंध में संग्रहीत किया जा सकता है।
अपने आप से पूछना सबसे अच्छा है कि आप किन तथ्यों को संग्रहीत करना चाहते हैं, आप किन सवालों के जवाब चाहते हैं, आप क्या रिपोर्ट तैयार करना चाहते हैं।
एक बार जब उचित DB डिज़ाइन बन जाता है, तो यह प्रश्न / विचार बनाने के लिए एक सरल मामला है जो आपको उन वस्तुओं के लिए अपनी वस्तुओं को क्रमबद्ध करने की अनुमति देता है।
उदाहरण:
होटल बुकिंग प्रणाली में, आपको इस तथ्य को संग्रहीत करने की आवश्यकता हो सकती है कि जेन डो को 10-12 अप्रैल के लिए सीव्यू इन में एक कमरे के लिए आरक्षण है। क्या यह ग्राहक इकाई का एक गुण है? क्या यह होटल इकाई का एक गुण है? क्या यह उन संपत्तियों के साथ आरक्षण इकाई है जिनमें ग्राहक और होटल शामिल हैं? यह ऑब्जेक्ट ओरिएंटेड सिस्टम में कोई भी या सभी चीजें हो सकती हैं। एक डेटाबेस में, यह उन चीजों में से कोई भी नहीं है। यह केवल एक नंगे तथ्य है।
अंतर देखने के लिए, निम्नलिखित दो प्रश्नों पर विचार करें। (१) जेन डो ने अगले साल कितने होटल आरक्षण लिए हैं? (२) सीव्यू इन में १० अप्रैल के लिए कितने कमरे बुक हैं?
ऑब्जेक्ट-ओरिएंटेड सिस्टम में, क्वेरी (1) ग्राहक इकाई की एक विशेषता है, और क्वेरी (2) होटल इकाई का एक गुण है। वे वस्तुएं हैं जो उन गुणों को अपने एपीआई में उजागर करेंगे। (हालांकि, स्पष्ट रूप से आंतरिक तंत्र जिसके द्वारा उन मूल्यों को प्राप्त किया जाता है, में अन्य वस्तुओं के संदर्भ शामिल हो सकते हैं।)
एक रिलेशनल डेटाबेस सिस्टम में, दोनों क्वेरीज़ अपने नंबरों को प्राप्त करने के लिए आरक्षण के संबंध की जांच करेंगे, और वैचारिक रूप से किसी अन्य "इकाई" के साथ परेशान होने की आवश्यकता नहीं है।
इस प्रकार, यह दुनिया के बारे में तथ्यों को संग्रहीत करने का प्रयास करके है - संस्थाओं के साथ विशेषताओं को संग्रहीत करने के प्रयास के बजाय - जो एक उचित संबंधपरक डेटाबेस का निर्माण किया जाता है। और एक बार जब यह ठीक से डिज़ाइन किया जाता है, तो उपयोगी प्रश्न जो कि डिजाइन चरण के दौरान पूर्ववत थे आसानी से बनाए जा सकते हैं, क्योंकि उन प्रश्नों को पूरा करने के लिए आवश्यक सभी तथ्य उनके उचित स्थानों पर हैं।
Employmentतालिका होनी चाहिए , जो अपनी शुरुआत की तारीखों के साथ सभी रोजगार एकत्र करती है। इसलिए यदि मौजूदा रोजगार की शुरुआत की तारीख जानना Employerमहत्वपूर्ण है, तो यह एक उचित उपयोग मामला हो सकता है View, जिसमें क्वेरी करके वह संपत्ति शामिल है? (ध्यान दें: ऐसा लगता है कि '-' के ठीक बाद मेरे निक के कारण मुझे आपकी टिप्पणी पर कोई सूचना नहीं मिली)
संक्षिप्त उत्तर: आप नहीं।
यदि आपको अपनी वस्तुओं को क्रमबद्ध करने की आवश्यकता है, तो ओआरएम का उपयोग करें, या एक्टिवरकॉर्ड या प्रबलता जैसी बेहतर चीज़ भी।
यदि आपको डेटा संग्रहीत करने की आवश्यकता है, तो इसे रिलेशनल तरीके से संग्रहीत करें (जो आप स्टोर कर रहे हैं, उसके बारे में सावधान रहें और जेफरी एल व्हिटलेज ने जो कहा है उस पर ध्यान दें), जो आपके ऑब्जेक्ट डिज़ाइन से प्रभावित नहीं है।
ब्रैड विल्सन द्वारा उल्लिखित टीपीटी, टीपीएच और टीपीसी पैटर्न आपके द्वारा जाने के तरीके हैं। लेकिन नोटों की जोड़ी:
बेस क्लास से विरासत में मिली चाइल्ड क्लासेस को डेटाबेस में बेस क्लास डेफिनिशन के लिए कमजोर-इकाइयाँ के रूप में देखा जा सकता है, जिसका अर्थ है कि वे अपने बेस-क्लास पर निर्भर हैं और इसके बिना मौजूद नहीं हो सकते। मैंने कई बार देखा है, कि प्रत्येक बच्चे के टेबल के लिए यूनिक आईडी जमा की जाती है, जबकि मूल तालिका में एफके को भी रखा जाता है। एक FK बस पर्याप्त है और इसका और भी बेहतर है कि बच्चे और आधार तालिकाओं के बीच FK-relation के लिए ऑन-कैस्केड सक्षम करें।
टीपीटी में, केवल बेस टेबल रिकॉर्ड को देखकर, आप यह पता नहीं कर पा रहे हैं कि रिकॉर्ड किस चाइल्ड क्लास का प्रतिनिधित्व कर रहा है। यह कभी-कभी आवश्यक होता है, जब आप सभी रिकॉर्ड की सूची लोड करना चाहते हैं ( select प्रत्येक और प्रत्येक बच्चे की मेज पर किए बिना )। इसे संभालने का एक तरीका है, एक कॉलम है कि चाइल्ड क्लास के प्रकार (टीपीएच में पंक्ति टाइप फील्ड के समान) का प्रतिनिधित्व करें, इसलिए टीपीटी और टीपीएच को किसी तरह मिलाएं।
मान लें कि हम एक डेटाबेस डिजाइन करना चाहते हैं जो निम्नलिखित आकार वर्ग आरेख रखता है:
public class Shape {
int id;
Color color;
Thickness thickness;
//other fields
}
public class Rectangle : Shape {
Point topLeft;
Point bottomRight;
}
public class Circle : Shape {
Point center;
int radius;
}
उपरोक्त कक्षाओं के लिए डेटाबेस का डिज़ाइन इस प्रकार हो सकता है:
table Shape
-----------
int id; (PK)
int color;
int thichkness;
int rowType; (0 = Rectangle, 1 = Circle, 2 = ...)
table Rectangle
----------
int ShapeID; (FK on delete cascade)
int topLeftX;
int topLeftY;
int bottomRightX;
int bottomRightY;
table Circle
----------
int ShapeID; (FK on delete cascade)
int centerX;
int center;
int radius;
विरासत के दो मुख्य प्रकार हैं जिन्हें आप डीबी में सेट कर सकते हैं, प्रति इकाई तालिका और पदानुक्रम प्रति तालिका।
प्रति इकाई तालिका वह जगह है जहां आपके पास एक आधार इकाई तालिका है जिसमें सभी बाल वर्गों के गुण हैं। तब आपके पास प्रति बच्चा एक अन्य तालिका होती है, जिसमें केवल उस वर्ग पर लागू गुण होते हैं। वे अपने पीके द्वारा 1: 1 से जुड़े हुए हैं

पदानुक्रम प्रति तालिका वह जगह है जहां सभी वर्गों ने एक तालिका साझा की है, और वैकल्पिक गुण शून्य हैं। उनका एक विभेदक क्षेत्र भी है जो एक संख्या है जो उस प्रकार को दर्शाता है जो वर्तमान में रिकॉर्ड रखता है
SessionTypeID भेदभाव करनेवाला है
प्रति पदानुक्रम लक्ष्य लक्ष्य के लिए तेज़ है क्योंकि आपको जॉइन करने की आवश्यकता नहीं है (केवल डिस्क्रिमिनेटर वैल्यू), जबकि प्रति यूनिट लक्ष्य आपको कॉम्प्लेक्स जॉइन करने की आवश्यकता है ताकि यह पता लगाया जा सके कि कुछ डेटा किस प्रकार का है और साथ ही अपने डेटा को पुनः प्राप्त करें।
संपादित करें: मैं जो चित्र यहां दिखाता हूं, मैं उस परियोजना के स्क्रीन शॉट्स हूं, जिस पर मैं काम कर रहा हूं। एसेट छवि पूर्ण नहीं है, इसलिए इसकी रिक्तता है, लेकिन यह मुख्य रूप से यह दिखाना है कि इसकी स्थापना कैसे हुई, न कि आपकी तालिकाओं के अंदर क्या रखा जाए। यह आप पर निर्भर है ;)। सत्र तालिका में वर्चुअल सहयोग सत्र की जानकारी होती है, और किस प्रकार का सहयोग शामिल है, इसके आधार पर कई प्रकार के सत्र हो सकते हैं।
आप अपने डेटाबेस का सामान्यीकरण करेंगे और यह वास्तव में आपके उत्तराधिकार को प्रतिबिंबित करेगा। इसमें प्रदर्शन की गिरावट हो सकती है, लेकिन यह सामान्यीकरण के साथ ऐसा है। आपको शायद संतुलन खोजने के लिए अच्छे सामान्य ज्ञान का उपयोग करना होगा।
इसी तरह के धागे के जवाब को दोहराएं
OR मैपिंग में, पैरेंट टेबल पर इनहेरिटेंस मैप्स जहां पैरेंट और चाइल्ड टेबल एक ही आइडेंटिफायर का उपयोग करते हैं
उदाहरण के लिए
create table Object (
Id int NOT NULL --primary key, auto-increment
Name varchar(32)
)
create table SubObject (
Id int NOT NULL --primary key and also foreign key to Object
Description varchar(32)
)
SubObject का ऑब्जेक्ट के लिए एक विदेशी-कुंजी संबंध है। जब आप एक SubObject पंक्ति बनाते हैं, तो आपको पहले एक ऑब्जेक्ट पंक्ति बनाना होगा और दोनों पंक्तियों में Id का उपयोग करना होगा
संपादित करें: यदि आप मॉडल के व्यवहार को भी देख रहे हैं, तो आपको एक प्रकार की तालिका की आवश्यकता होगी, जो तालिकाओं के बीच वंशानुक्रम संबंधों को सूचीबद्ध करती है, और प्रत्येक तालिका के व्यवहार को लागू करने वाले विधानसभा और वर्ग के नाम को निर्दिष्ट करती है
ओवरकिल जैसा लगता है, लेकिन यह सब इस बात पर निर्भर करता है कि आप इसके लिए क्या उपयोग करना चाहते हैं!
SQL कीमिया (पायथन ओआरएम) का उपयोग करके, आप दो प्रकार के वंशानुक्रम कर सकते हैं।
मेरे पास जो अनुभव है वह एक सिंग-टेबल का उपयोग कर रहा है, और एक भेदभावपूर्ण कॉलम है। उदाहरणों के लिए, एक भेड़ डेटाबेस (कोई मजाक नहीं!) ने सभी भेड़ें एक ही तालिका में संग्रहीत कीं, और उस तालिका में एक लिंग स्तंभ का उपयोग करके राम और इव्स को संभाला गया।
इस प्रकार, आप सभी भेड़ों के लिए क्वेरी कर सकते हैं, और सभी भेड़ें प्राप्त कर सकते हैं। या आप केवल राम द्वारा प्रश्न कर सकते हैं, और यह केवल राम मिलेगा। आप ऐसी चीजें भी कर सकते हैं जैसे एक रिश्ता है जो केवल एक राम (यानी, एक भेड़ का बच्चा) हो सकता है, और इसी तरह।
ध्यान दें कि कुछ डेटाबेस इंजन पहले से ही वंशानुगत तंत्र प्रदान करते हैं जैसे पोस्टग्रेज । को देखो प्रलेखन ।
एक उदाहरण के लिए, आप इस तरह से ऊपर की प्रतिक्रिया में वर्णित व्यक्ति / कर्मचारी प्रणाली को क्वेरी करेंगे:
/ * यह सभी व्यक्तियों या कर्मचारियों का पहला नाम दर्शाता है * / व्यक्ति से पहला नाम चुनें; / * यह केवल सभी कर्मचारियों की आरंभ तिथि दर्शाता है * / कर्मचारी से आरंभ का चयन करें;
इसमें आपके डेटाबेस का विकल्प है, आपको विशेष रूप से स्मार्ट होने की आवश्यकता नहीं है!