5

शीर्षक के लिए खेद है, यह समझाना मुश्किल है। alt textMySQL: दो एन: 1 संबंध, लेकिन दोनों एक बार में नहीं

आप देख सकते हैं, एक सेट दोनों एक उपयोगकर्ता या एक स्कूल से सम्बंधित कर सकते हैं:

मैं इस के समान एक डाटा मॉडल की जरूरत है। मेरी समस्या: इसे केवल उपयोगकर्ता या स्कूल से संबंधित होने की अनुमति दी जानी चाहिए। लेकिन दोनों एक ही समय में कभी नहीं।

मैं इस समस्या को कैसे हल कर सकता हूं?

+0

ग्राफिक बनाने के लिए आपने क्या उपयोग किया? – basszero

+0

@basszero: MySQL वर्कबेंच –

+0

वाह! आखिरकार यह कोशिश करने के बाद से यह एक लंबा सफर तय हुआ है! – basszero

उत्तर

6

आपके वर्तमान डिजाइन को विशेष आर्क्स कहा जाता है जहां sets तालिका में दो विदेशी कुंजी हैं, और उनमें से एक को गैर-शून्य होने की आवश्यकता है। यह पॉलिमॉर्फिक एसोसिएशन को लागू करने का एक तरीका है, क्योंकि एक दी गई विदेशी कुंजी केवल एक लक्ष्य तालिका का संदर्भ दे सकती है।

एक और समाधान एक आम "सुपरटेबल" बनाना है जो users और schools दोनों संदर्भों का उपयोग करता है, और उसके बाद sets के माता-पिता के रूप में उपयोग करें।

create table set_owner 

create table users 
    PK is also FK --> set_owner 

create table schools 
    PK is also FK --> set_owner 

create table sets 
    FK --> set_owner 

आप OO मॉडलिंग में एक इंटरफ़ेस को यह रूप में अनुरूप के बारे में सोच सकते हैं:

interface SetOwner { ... } 

class User implements SetOwner { ... } 

class School implements SetOwner { ... } 

class Set { 
    SetOwner owner; 
} 

अपनी टिप्पणी पुन:

तो SetOwner तालिका दोनों UserIDs शामिल और स्कूल आईडी, सही? इसका मतलब यह होगा कि मुझे उपयोगकर्ता और स्कूल के लिए एक ही आईडी रखने की अनुमति नहीं दी जाएगी। मैं इसे कैसे लागू कर सकता हूं?

सेटऑनर्स तालिका आईडी मान उत्पन्न करने दें। इससे पहले कि आप उपयोगकर्ता या स्कूल में सम्मिलित कर सकें, आपको सेटऑनर्स में डालना होगा। तो आईडी और उपयोगकर्ताओं में स्कूल ऑटो-वृद्धिशीलता बनाएं; बस SetOwners द्वारा उत्पन्न किए गए मान का उपयोग करें:

INSERT INTO SetOwners DEFAULT VALUES; -- generates an id 
INSERT INTO Schools (id, name, location) VALUES (LAST_INSERT_ID(), 'name', 'location'); 

इस प्रकार कोई भी आईडी मान स्कूल और उपयोगकर्ता दोनों के लिए उपयोग नहीं किया जाएगा।

अगर मैं एक सेट के लिए मालिक का प्रकार प्राप्त करना चाहता हूं, तो क्या मुझे अपने SetOwner तालिका में एक मालिक टाइप प्रकार की आवश्यकता है?

आप निश्चित रूप से ऐसा कर सकते हैं। वास्तव में, ऐसे अन्य कॉलम हो सकते हैं जो उपयोगकर्ता और स्कूल दोनों के लिए आम हैं, और आप इन कॉलम को प्राप्य सेटऑनर्स में डाल सकते हैं। यह मार्टिन फाउलर के Class Table Inheritance पैटर्न में मिलता है।

और अगर मैं स्कूल या उपयोगकर्ता (यह जो भी प्रकार) के नाम पर प्राप्त करना चाहते हैं, मैं इस एक क्वेरी के साथ कर सकते हैं, या मैं दो प्रश्नों की जरूरत है (पहले प्रकार और दूसरा पाने के लिए क्या नाम पाने के लिए)?

आपको शामिल होने की आवश्यकता है। यदि आप किसी दिए गए सेट से पूछताछ कर रहे हैं और आप जानते हैं कि यह किसी उपयोगकर्ता (स्कूल नहीं है) से संबंधित है, तो आप SetOwners में शामिल होने और सीधे उपयोगकर्ताओं से जुड़ने के लिए छोड़ सकते हैं। जॉइन को जरूरी नहीं कि विदेशी चाबियाँ हों।

SELECT u.name FROM Sets s JOIN Users u ON s.SetOwner_id = u.id WHERE ... 

आप नहीं जानते कि किसी दिए गए सेट एक उपयोगकर्ता या एक स्कूल के अंतर्गत आता है, चाहे आप एक बाहरी कर दिया था दोनों में शामिल होने:

SELECT COALESCE(u.name, sc.name) AS name 
FROM Sets s 
LEFT OUTER JOIN Users u ON s.SetOwner_id = u.id 
LEFT OUTER JOIN Schools sc ON s.SetOwner_id = sc.id 
WHERE ... 

तुम्हें पता है कि SetOwner_id चाहिए एक या दूसरी तालिका, उपयोगकर्ता या स्कूल से मेल खाते हैं, लेकिन दोनों नहीं।

+0

महान स्पष्टीकरण के लिए धन्यवाद। प्रबल के साथ दृष्टिकोण उस टिप्पणी के समान लगता है जो भूगर्भलन ने अपनी टिप्पणी में प्रस्तावित किया था। मुझे लगता है कि अब मैं अवधारणा को समझता हूं। तो 'SetOwner' तालिका में उपयोगकर्ता आईडी और स्कूल आईडी दोनों हैं, सही? इसका मतलब यह होगा कि मुझे उपयोगकर्ता और स्कूल के लिए एक ही आईडी रखने की अनुमति नहीं दी जाएगी। मैं इसे कैसे लागू कर सकता हूं? –

+0

और दूसरा पहलू: ईआरडी वर्तमान में इस http://imgur.com/vD1ln.png जैसा दिखता है।अगर मैं एक सेट के लिए मालिक का प्रकार प्राप्त करना चाहता हूं, तो क्या मुझे अपने SetOwner तालिका में एक मालिक टाइप प्रकार की आवश्यकता है? या ऐसा करने का कोई और तरीका है? और अगर मैं स्कूल या उपयोगकर्ता का नाम प्राप्त करना चाहता हूं (जो भी इसे टाइप करता है), क्या मैं इसे एक ही प्रश्न के साथ कर सकता हूं, या मुझे दो प्रश्नों की आवश्यकता है (पहले नाम पाने के लिए टाइप और दूसरा प्राप्त करने के लिए)? –

+0

बहुत बढ़िया संपादन, धन्यवाद। यही कारण है कि मैं Stackoverflow प्यार करता हूँ। केवल एक शेष प्रश्न है: क्या मैं एक बहुउद्देशीय वातावरण में सुरक्षित रूप से 'LAST_INSERT_ID()' का उपयोग कर सकता हूं, या अन्य उपयोगकर्ताओं द्वारा क्वेरी और आवेषण वर्तमान क्वेरी में हस्तक्षेप कर सकता है, ताकि LAST_INSERT_ID बदल जाए? –

1

आपको इस व्यवसाय नियम को लागू करने के लिए एक ट्रिगर का उपयोग करना होगा, क्योंकि MySQL ने जांच बाधाओं (किसी भी इंजन पर) को लागू नहीं किया है।

2

चेतावनी के साथ: यह पूरी तरह से स्पष्ट नहीं है कि आपके डेटा मॉडल में एक सेट क्या है।

मैं आपके डेटा मॉडल पर सवाल कर रहा हूं।

उपयोगकर्ता -> सेट और स्कूल -> सेट को एक ही टेबल पर इंगित करना क्यों है। यदि यह वास्तव में डेटा के स्वतंत्र सेट हैं तो यह अधिक सामान्य नहीं है। सिर्फ इसलिए कि वे कॉलम में कुछ समानताएं साझा करते हैं जिन्हें वे ट्रैक करते हैं इसका मतलब यह नहीं है कि उन्हें एक ही तालिका में संग्रहीत किया जाना चाहिए। क्या वे तार्किक रूप से एक ही बात हैं?

बस स्कूल सेट्स और उपयोगकर्ता समूह के लिए अलग-अलग टेबल बनाएं। यह विपरीत प्रश्नों को भी आसान बना देगा क्योंकि आपको यह सेट करने के लिए सेट टेबल में शून्य संबंधों की जांच नहीं करनी होगी कि यह वास्तव में उपयोगकर्तासेट या स्कूलसेट है या नहीं।

+0

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

+0

आप शायद उपयोगकर्ता/स्कूलों और सेट्स के बीच एक सेटऑनर तालिका डाल सकते हैं। फिर प्रत्येक तालिका में 'सेट' रखने वाली प्रत्येक तालिका में एक set_owner_id पर एक FK कॉलम होगा। सेट टेबल के बाद एक set_owner_id भी होगा। तो मूल रूप से एक उपयोगकर्ता और स्कूल के पास SetOwner और SetOwner के लिए 1: 1 संबंध होता है 1: सेट करने के लिए एम। तब सब कुछ लागू करने योग्य संदर्भित अखंडता है। इससे सेट टू स्वामी (तार्किक) में जाना मुश्किल हो जाएगा। – geofflane

+0

आपका मतलब यह है? http://i.imgur.com/dVRs9.png मैं वास्तव में समझ में नहीं आता कि यह समस्या को कैसे हल करता है। –

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