आप विरासत का उपयोग कर रहे हैं (जिसे इकाई-संबंध मॉडलिंग में "उपवर्ग" या "श्रेणी" के रूप में भी जाना जाता है)। सामान्य तौर पर, डेटाबेस में इसका प्रतिनिधित्व करने के 3 तरीके हैं:
- "सभी कक्षाएं एक टेबल में": माता-पिता और सभी बाल वर्गों (यानी सभी माता-पिता और बच्चे के कॉलम के साथ) को "कवर" करने के लिए केवल एक टेबल है, यह सुनिश्चित करने के लिए चेक बाधा के साथ फ़ील्ड का सही सबसेट गैर-नल है (यानी दो अलग-अलग बच्चे "मिश्रण" नहीं करते हैं)।
- "प्रति तालिका कंक्रीट वर्ग": प्रत्येक बच्चे के लिए एक अलग टेबल है, लेकिन कोई पैरेंट टेबल नहीं है। इसके लिए माता-पिता के रिश्ते (आपके मामले में इन्वेंटरी <- स्टोरेज) को सभी बच्चों में दोहराया जाना आवश्यक है।
- "प्रति तालिका कक्षा": प्रत्येक बच्चे के लिए एक पैरेंट टेबल और एक अलग टेबल होना, जो आप करने की कोशिश कर रहे हैं। यह सबसे साफ है, लेकिन कुछ प्रदर्शन खर्च कर सकते हैं (ज्यादातर डेटा को संशोधित करते समय, पूछताछ करते समय इतना अधिक नहीं क्योंकि आप सीधे बच्चे से जुड़ सकते हैं और माता-पिता को छोड़ सकते हैं)।
मैं आमतौर पर तीसरा दृष्टिकोण पसंद करता हूं, लेकिन उपस्थिति . दोनों को लागू करता हूं और विशिष्टता आवेदन स्तर पर एक बच्चे की। डेटाबेस स्तर पर दोनों को लागू करना थोड़ा बोझिल है, लेकिन यह किया जा सकता है यदि DBMS आस्थगित बाधाओं का समर्थन करता है। उदाहरण के लिए:
CHECK (
(
(VAN_ID IS NOT NULL AND VAN_ID = STORAGE_ID)
AND WAREHOUSE_ID IS NULL
)
OR (
VAN_ID IS NULL
AND (WAREHOUSE_ID IS NOT NULL AND WAREHOUSE_ID = STORAGE_ID)
)
)
यह दोनों विशिष्टता को लागू करेगा (CHECK
. के कारण ) और उपस्थिति (CHECK
. के संयोजन के कारण) और FK1
/FK2
) बच्चे की।
दुर्भाग्य से, MS SQL सर्वर आस्थगित बाधाओं का समर्थन नहीं करता है, लेकिन आप संग्रहीत प्रक्रियाओं के पीछे पूरे ऑपरेशन को "छिपाने" में सक्षम हो सकते हैं और क्लाइंट को सीधे तालिकाओं को संशोधित करने से मना कर सकते हैं।
आस्थगित बाधाओं के बिना केवल विशिष्टता को लागू किया जा सकता है:
STORAGE_TYPE
एक प्रकार का विभेदक है, आमतौर पर स्थान बचाने के लिए एक पूर्णांक (उपरोक्त उदाहरण में, 0 और 1 आपके आवेदन के लिए "ज्ञात" हैं और तदनुसार व्याख्या की गई है)।
VAN.STORAGE_TYPE
और WAREHOUSE.STORAGE_TYPE
भंडारण को बचाने और CHECK
की आवश्यकता से बचने के लिए गणना की जा सकती है (उर्फ "गणना") कॉलम स.
--- संपादित करें ---
कंप्यूटेड कॉलम SQL सर्वर के तहत इस तरह काम करेंगे:
CREATE TABLE STORAGE (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE tinyint NOT NULL,
UNIQUE (STORAGE_ID, STORAGE_TYPE)
);
CREATE TABLE VAN (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE AS CAST(0 as tinyint) PERSISTED,
FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
);
CREATE TABLE WAREHOUSE (
STORAGE_ID int PRIMARY KEY,
STORAGE_TYPE AS CAST(1 as tinyint) PERSISTED,
FOREIGN KEY (STORAGE_ID, STORAGE_TYPE) REFERENCES STORAGE(STORAGE_ID, STORAGE_TYPE)
);
-- We can make a new van.
INSERT INTO STORAGE VALUES (100, 0);
INSERT INTO VAN VALUES (100);
-- But we cannot make it a warehouse too.
INSERT INTO WAREHOUSE VALUES (100);
-- Msg 547, Level 16, State 0, Line 24
-- The INSERT statement conflicted with the FOREIGN KEY constraint "FK__WAREHOUSE__695C9DA1". The conflict occurred in database "master", table "dbo.STORAGE".
दुर्भाग्य से, SQL सर्वर को एक परिकलित कॉलम की आवश्यकता होती है जो एक विदेशी में उपयोग किया जाता है जारी रखने की कुंजी। अन्य डेटाबेस में यह सीमा नहीं हो सकती है (जैसे Oracle के वर्चुअल कॉलम), जो कुछ संग्रहण स्थान बचा सकते हैं।