6

मैं एक डेटाबेस कई तालिकाओं के साथ की स्थापना की है और यह सब अलग एक बिट से अच्छा लग रहा है ...कैसे किसी के

Inventory Table <*-----1> Storage Table <1-----1> Van Table 
          ^
           1 
           |-------1> Warehouse Table 

संग्रहण तालिका वान के बाद से इस्तेमाल किया जाता है और गोदाम तालिका करने के लिए कई एक बनाने के लिए कर रहे हैं समान लेकिन मैं स्टोरेज और वेयरहाउस/वैन टेबल के बीच संबंध कैसे बना सकता हूं? यह समझ में आता है कि उन्हें 1 से 1 होने की आवश्यकता है क्योंकि स्टोरेज ऑब्जेक्ट केवल 1 संग्रहण स्थान और प्रकार हो सकता है। मेरे पास स्टोरेज आईडी प्राथमिक कुंजी के लिए वैन/वेयरहाउस टेबल लिंक था और फिर यह सुनिश्चित करने के लिए एक बाधा जोड़ें कि वैन और वेयरहाउस टेबलों में एक ही स्टोरेज आईडी नहीं है, लेकिन ऐसा लगता है कि इसे बेहतर तरीके से किया जा सकता है।

मैं ऐसा करने के कई तरीके देख सकता हूं लेकिन वे सभी गलत लगते हैं, इसलिए कोई मदद अच्छी होगी!

+0

कृपया अच्छी तरह से मूल्यांकन करता है, तो आप वास्तव में एक रिश्ते के लिए एक की जरूरत है। अधिकांश समय जब आपको लगता है कि आपको एक की जरूरत है, तो आप वास्तव में नहीं करते हैं। –

+0

ईईआर का प्रयोग करें। यहां की कुंजी रिश्ते के प्रकार की पहचान करना है 'है', 'है'/'से संबंधित है, या वे एक ही सुपरटेप के उपप्रकार हैं। फिर अपनी इकाइयों को टेबल पर कम करें। – Oybek

+0

आह ठीक है, तो फिर स्टोरेज टेबल एक सुपरक्लास है और वैन/वेयरहाउस टेबल्स उपप्रकार हैं, लेकिन अब क्या? lol – Luckyl337

उत्तर

15

आप विरासत का उपयोग कर रहे हैं (इकाई-संबंध मॉडलिंग में "सबक्लास" या "श्रेणी" के रूप में भी जाना जाता है)।

  1. "सभी एक तालिका में वर्ग": सिर्फ एक मेज सभी माता पिता और बच्चे के साथ माता-पिता और बच्चों की कक्षाएं (यानी "कवर" है सामान्य में, वहाँ डेटाबेस में यह प्रतिनिधित्व करने के लिए 3 तरीके हैं कॉलम), एक जांच की बाधा के साथ फ़ील्ड का सही सबसेट गैर-नल (यानी दो अलग-अलग बच्चे "मिश्रण" नहीं करते हैं)।
  2. "प्रति तालिका कंक्रीट वर्ग": प्रत्येक बच्चे के लिए एक अलग टेबल है, लेकिन कोई अभिभावक तालिका नहीं है। इसके लिए माता-पिता के संबंधों की आवश्यकता होती है (आपके मामले में सूची < - संग्रहण) सभी बच्चों में दोहराया जाना चाहिए।
  3. "कक्षा प्रति वर्ग": प्रत्येक बच्चे के लिए अभिभावक तालिका और एक अलग तालिका होने के नाते, जो आप करने की कोशिश कर रहे हैं। यह सबसे साफ है, लेकिन कुछ प्रदर्शन खर्च कर सकते हैं (ज्यादातर डेटा संशोधित करते समय, पूछताछ करते समय इतना नहीं, क्योंकि आप सीधे बच्चे से जुड़ सकते हैं और माता-पिता को छोड़ सकते हैं)।

मैं आमतौर पर 3 प्रक्रिया अपनाते हैं, लेकिन दोनों उपस्थिति और आवेदन स्तर पर एक बच्चे की विशिष्टता लागू। डेटाबेस स्तर पर दोनों को लागू करना थोड़ा बोझिल है, लेकिन डीबीएमएस स्थगित बाधाओं का समर्थन करता है तो किया जा सकता है। उदाहरण के लिए:

enter image description here

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 के कारण) को लागू करेगा।

दुर्भाग्यवश, एमएस एसक्यूएल सर्वर does not support deferred constraints, लेकिन आप संग्रहीत प्रक्रियाओं के पीछे पूरे ऑपरेशन को "छिपाने" में सक्षम हो सकते हैं और ग्राहकों को सीधे टेबल को संशोधित करने से मना कर सकते हैं।


बस विशिष्टता टाल बाधाओं के बिना लागू किया जा सकता:

enter image description here

STORAGE_TYPE एक प्रकार discriminator, आमतौर पर एक (उपरोक्त उदाहरण में स्थान बचाने के लिए पूर्णांक है, 0 और 1 हैं " ज्ञात "आपके आवेदन के लिए और तदनुसार व्याख्या की गई)।

VAN.STORAGE_TYPE और WAREHOUSE.STORAGE_TYPE (उर्फ। "गणना") कॉलम भंडारण बचाने के लिए और CHECK रों के लिए जरूरत से बचने के लिए की जा सकती है।

--- संपादित करें ---

परिकलित स्तंभों इस तरह एसक्यूएल सर्वर के तहत काम करेगा:

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". 

दुर्भाग्य से, एसक्यूएल सर्वर एक गणना स्तंभ जो एक विदेशी में प्रयोग किया जाता है के लिए की आवश्यकता है की पेशकश की जाने वाली कुंजी। अन्य डेटाबेस में यह सीमा नहीं हो सकती है (उदा। ओरेकल के आभासी कॉलम), जो कुछ संग्रहण स्थान को बचा सकता है।

+0

हाय @ ब्रैंको, महान उत्तर के लिए धन्यवाद। हालांकि, मैं आपकी प्रतिक्रिया के अंतिम कुछ वाक्यों से उलझन में था। क्या आप इस पर विस्तार से ध्यान देंगे: (1) क्यों, आपके आखिरी आरेख में, वैन और वॉरहाउस टेबल में STORAGE_TYPE कॉलम है (मुझे कल्पना है, सभी एक ही मान के साथ: VAN के लिए 0 और वॉरहाउस के लिए 1), (2) वास्तव में क्या है गणना/गणना कॉलम की सामग्री में जाना चाहिए (मैं इस बारे में उलझन में हूं कि यहां क्या गणना की जा रही है)? बहुत बाध्य :) – youngrrrr

+1

@youngrrrr वैन और वॉरहाउस में STORAGE_TYPE है ताकि वे उस पर एक जांच घोषित कर सकें। इस तरह, यदि एक स्टोरेज पंक्ति VAN पंक्ति का अभिभावक है, तो यह _cannot_ भी वॉरहाउस पंक्ति का अभिभावक हो सकता है (क्योंकि STORAGE.STORAGE_TYPE 0 है, वॉरहाउस में जांच विफल रहा है)। इसके विपरीत यह भी सच है: अगर स्टोरेज वॉरहाउस है, तो स्टोरेज टाइप 1 है, जिसका अर्थ है कि वीएएन में जांच विफल हो जाएगी अगर किसी ने वहां एक संबंधित पंक्ति डालने का प्रयास किया हो। गणना कॉलम बस अंतरिक्ष को बचाने के लिए है - क्योंकि यह हमेशा दी गई तालिका के भीतर एक ही मान है, इसलिए प्रत्येक पंक्ति में उस मान को भौतिक रूप से दोहराने की आवश्यकता नहीं है। –

+1

@youngrrrr कृपया ध्यान दें कि STORAGE (STORAGE_ID, STORAGE_TYPE) संदर्भित VAN (STORAGE_ID, स्टोरेज) पर एक FK है। और वॉरहाउस पर भी। इस तरह, माता-पिता पंक्ति (स्टोरेज में) और बाल पंक्ति (वैन या वॉरहाउस में, लेकिन दोनों नहीं) हमेशा एक ही STORAGE_TYPE होती है। –

1

जैसा कि आप कहते हैं, कई समाधान हैं। मैं सबसे सरल समाधान से शुरू करने की सलाह दूंगा, फिर प्रदर्शन या भंडारण समस्याएं बनने के बाद बाद में अनुकूलन करूँगा। सबसे सरल समाधान (लेकिन भंडारण के मामले में इष्टतम नहीं) में एक भंडारण तालिका होगी जिसमें भंडारण प्रकार के लिए एक कॉलम होगा (यह दर्शाता है कि पंक्ति वैन या वेयरहाउस का प्रतिनिधित्व करती है), साथ ही वैन विशेषताओं के साथ-साथ वेयरहाउस विशेषताओं के कॉलम भी हैं। एक पंक्ति में जो एक वैन का प्रतिनिधित्व करता है, वेयरहाउस विशेषताओं के कॉलम सभी शून्य हो जाएंगे। वेयरहाउस का प्रतिनिधित्व करने वाली एक पंक्ति में, वैन विशेषताओं के कॉलम सभी शून्य हो जाएंगे।

इस तरह, आप टेबल की संख्या में कटौती करते हैं, और अपने प्रश्नों को अच्छे और सरल रखते हैं। भंडारण तंग होने पर अपने निर्णय पर फिर से विचार करने के लिए तैयार रहें।

1

किसी भी तरह से मुझे लगता है कि सूची-वस्तुएं स्थान बदल सकती हैं, इसलिए मैं इस तरह कुछ के साथ जाऊंगा।

enter image description here

संबंधित मुद्दे