विशेषाधिकार प्राप्त बच्चे के साथ एक-से-कई संबंध कैसे हैं?


22

मैं एक-से-एक संबंध रखना चाहता हूं, जिसमें प्रत्येक माता-पिता के लिए, बच्चों में से एक या शून्य को "पसंदीदा" के रूप में चिह्नित किया जाता है, हालांकि, प्रत्येक माता-पिता के पास एक बच्चा नहीं होगा। (इस साइट पर प्रश्नों के रूप में माता-पिता के बारे में सोचें, उत्तर के रूप में बच्चे, और स्वीकृत उत्तर के रूप में पसंदीदा।) उदाहरण के लिए।

TableA
    Id            INT PRIMARY KEY

TableB
    Id            INT PRIMARY KEY
    Parent        INT NOT NULL FOREIGN KEY REFERENCES TableA.Id

जिस तरह से मैं इसे देखता हूं, मैं या तो निम्नलिखित कॉलम को टेबलए में जोड़ सकता हूं:

    FavoriteChild INT NULL FOREIGN KEY REFERENCES TableB.Id

या निम्न स्तंभ को TableB:

    IsFavorite    BIT NOT NULL

पहले दृष्टिकोण के साथ समस्या यह है कि यह एक अशक्त विदेशी कुंजी का परिचय देता है, जो मुझे समझ में आता है, सामान्यीकृत रूप में नहीं है। दूसरे दृष्टिकोण के साथ समस्या यह है कि यह सुनिश्चित करने के लिए अधिक काम किए जाने की आवश्यकता है कि ज्यादातर एक बच्चे का पसंदीदा है।

किस दृष्टिकोण का उपयोग करने के लिए मुझे किस प्रकार के मापदंड का उपयोग करना चाहिए? या, क्या अन्य दृष्टिकोण हैं जिन पर मैं विचार नहीं कर रहा हूं?

मैं SQL Server 2012 का उपयोग कर रहा हूं।

जवाबों:


19

एक और तरीका है ( FOREIGN KEYरिश्तों में Nulls और बिना साइकिल के) "पसंदीदा बच्चों" को संग्रहीत करने के लिए एक तीसरी तालिका है। अधिकांश DBMS में, आपको एक अतिरिक्त UNIQUEबाधा की आवश्यकता होगी TableB

@ एरन यह पहचानने के लिए तेज़ था कि ऊपर दिया गया नामकरण सम्मेलन बोझिल है और इससे त्रुटियां हो सकती हैं। यदि आप Idअपनी सभी मेजों पर कॉलम नहीं रखते हैं और यदि कॉलम (जो जुड़ गए हैं) तो कई तालिकाओं में समान नाम होते हैं, तो यह आमतौर पर बेहतर होता है (और आपको सन्न रखेगा) । इसलिए, यहाँ एक नामकरण है:

Parent
    ParentID        INT NOT NULL PRIMARY KEY

Child
    ChildID         INT NOT NULL PRIMARY KEY
    ParentID        INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
    UNIQUE (ParentID, ChildID)

FavoriteChild
    ParentID        INT NOT NULL PRIMARY KEY
    ChildID         INT NOT NULL 
    FOREIGN KEY (ParentID, ChildID) 
        REFERENCES Child (ParentID, ChildID)

SQL- सर्वर में (जो आप उपयोग कर रहे हैं), आपके पास आपके द्वारा IsFavoriteउल्लेखित बिट कॉलम का विकल्प भी है । माता-पिता के प्रति अद्वितीय पसंदीदा बच्चे को फ़िल्टर किए गए अनन्य सूचकांक के माध्यम से पूरा किया जा सकता है:

Parent
    ParentID        INT NOT NULL PRIMARY KEY

Child
    ChildID         INT NOT NULL PRIMARY KEY
    ParentID        INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
    IsFavorite      BIT NOT NULL

CREATE UNIQUE INDEX is_FavoriteChild
  ON Child (ParentID)
  WHERE IsFavorite = 1 ;

और मुख्य कारण यह है कि आपका विकल्प 1 अनुशंसित नहीं है, कम से कम SQL-Server में नहीं है, यह है कि विदेशी कुंजी संदर्भों में परिपत्र पथ के पैटर्न में कुछ समस्याएं हैं।

एक काफी पुराना लेख पढ़ें: SQL बाइ डिजाइन: सर्कुलर संदर्भ

दो तालिका से पंक्तियाँ सम्मिलित या हटाते समय, आप "चिकन-एंड-एग" समस्या में भाग लेंगे। किसी अड़चन का उल्लंघन किए बिना मुझे कौन सी तालिका पहले सम्मिलित करनी चाहिए?

इसे हल करने के लिए, आपको कम से कम एक कॉलम को अशक्त करना होगा। (ठीक है, तकनीकी रूप से आप के लिए, यदि आप सभी कॉलम हो सकता है की जरूरत नहीं है के रूप में NOT NULL, लेकिन केवल डीबीएमएस, Postgres और Oracle की तरह, कि deferrable की कमी को लागू किया है देखें @ एक ऐसी ही सवाल में इरविन के जवाब में:। SQLAlchemy में परिसर विदेशी कुंजी बाधा पर कैसे यह Postgres में किया जा सकता है)। फिर भी, यह सेटअप पतली बर्फ पर स्केटिंग करने जैसा लगता है।

एसओ (लेकिन MySQL के लिए) एसक्यूएल में भी लगभग एक समान प्रश्न की जाँच करें , क्या दो तालिकाओं के लिए एक-दूसरे को संदर्भित करना ठीक है? जहां मेरा जवाब बहुत ज्यादा एक ही है। MySQL के पास हालांकि कोई आंशिक अनुक्रमणिका नहीं है, इसलिए एकमात्र व्यवहार्य विकल्प अशक्त FK और अतिरिक्त तालिका समाधान हैं।


9

यह इस बात पर निर्भर करता है कि आपकी प्राथमिकता क्या है। क्या आप काम से बचना चाहते हैं या आप सामान्यीकरण के सख्त नियमों का पालन करना चाहते हैं?

व्यक्तिगत रूप से, मुझे लगता है IsFavoriteकि बच्चे की तालिका में होना बेहतर है , और यह सुनिश्चित करने के लिए काम करने के लिए तैयार होगा कि प्रत्येक माता-पिता के लिए कम से कम एक बच्चा उस माता-पिता का पसंदीदा है। प्राथमिक कारण का अशांत विदेशी कुंजी के साथ कोई लेना-देना नहीं है: मुझे दोनों दिशाओं में इंगित विदेशी कुंजी के विचार बिल्कुल पसंद नहीं हैं।

@ ypercube का सुझाव एक अच्छा समझौता है।

एक तरफ के रूप में, कृपया, कृपया, कृपया अपने स्कीमा को अर्थहीन कॉलम नामों जैसे लिट न करें Id। मैं बहुत अधिक बल्कि Idपूरे स्कीमा में एक सार्थक तरीके से नामित होने के लिए देखूंगा । क्या यह एक लेखक की पहचान करता है? ठीक है, बुलाओ AuthorID। क्या यह किसी उत्पाद का प्रतिनिधित्व करता है? ठीक है, ProductID। क्या यह एक कर्मचारी है, और कुछ मामलों में एक प्रबंधक को संदर्भित करता है? ठीक है, EmployeeIDऔर ManagerIDमेरे लिए और अधिक समझ में आता है IDऔर Parent। हालाँकि, जब आप कॉम्प्लेक्स जॉइन (या पोस्ट क्वेश्चन) लिखना शुरू करते हैं, तो इसे छोड़ना तर्कसंगत होगा (और इसे डालने के लिए बेमानी है), आप निश्चित रूप से कुछ कोस को महसूस करेंगे जब आप इंजीनियर को उस बिंदु से जुड़ने की कोशिश कर रहे होंगे। जैसे कॉलम a.Parent = b.ID... ब्लोच।


1

डेटा चाइल्ड टेबल में है। हम यह सुनिश्चित करने के लिए मेज पर एक ट्रिगर के साथ इसे सही रखते हैं और केवल रिकॉर्ड को पसंदीदा (या हमारे मामले में पसंदीदा पते के रूप में) के रूप में चिह्नित किया जाता है।

हालाँकि, @ ypercube का एक अलग तालिका का विचार एक अच्छा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.