कई तालिकाओं में प्राथमिक कुंजियों की चर्चा करते हुए विदेशी कुंजी?


91

डेटाबेस कर्मचारियों के तहत मेरे पास दो टेबल हैं, जैसे कि कर्मचारियों के कर्मचारी और कर्मचारी_एसएन।

उन दोनों के पास अपने संबंधित विशिष्ट प्राथमिक कुंजी कॉलम हैं।

मेरे पास एक और तालिका है जिसे कटौती कहा जाता है, जिसका विदेशी कुंजी कॉलम मैं कर्मचारियों की प्राथमिक कुंजी के साथ-साथ कर्मचारी_एसएन का संदर्भ देना चाहता हूं। क्या यह संभव है?

उदाहरण के लिए

employees_ce
--------------
empid   name
khce1   prince

employees_sn
----------------
empid   name
khsn1   princess

क्या यह संभव है?

deductions
--------------
id      name
khce1   gold
khsn1   silver

जवाबों:


98

यह मानते हुए कि मैंने आपके परिदृश्य को सही ढंग से समझा है, यह वही है जो मैं इसे करने का सही तरीका कहूंगा :

अपने डेटाबेस के उच्च-स्तरीय विवरण से प्रारंभ करें! आपके पास कर्मचारी हैं, और कर्मचारी "CE" कर्मचारी और "स्न" कर्मचारी (जो भी हैं) हो सकते हैं। वस्तु-उन्मुख शब्दों में, एक वर्ग "कर्मचारी" है, जिसमें दो उप-वर्ग हैं, जिन्हें "सीई कर्मचारी" और "स्न कर्मचारी" कहा जाता है।

तो फिर तुम तीन तालिकाओं के लिए इस उच्च स्तर के वर्णन का अनुवाद: employees, employees_ceऔर employees_sn:

  • employees(id, name)
  • employees_ce(id, ce-specific stuff)
  • employees_sn(id, sn-specific stuff)

चूंकि सभी कर्मचारी कर्मचारी (डुह!) हैं, इसलिए प्रत्येक कर्मचारी की employeesतालिका में एक पंक्ति होगी । "सी" कर्मचारियों की employees_ceतालिका में एक पंक्ति भी होती है , और "एसई" कर्मचारियों की भी employees_snतालिका में एक पंक्ति होती है । employees_ce.idजैसा है employees.idवैसा ही एक विदेशी कुंजी employees_sn.idहै।

किसी भी प्रकार के कर्मचारी (सी.ई. या एस.एन.) को संदर्भित करने के लिए, employeesतालिका देखें । यही है, जिस विदेशी कुंजी से आपको परेशानी थी, उस तालिका को संदर्भित करना चाहिए!


17
आप CE और स्न को परस्पर अनन्य कैसे बनाते हैं? चूँकि एक कर्मचारी एक ही समय में CE और sn नहीं हो सकता है, इसलिए डेटाबेस में इसे प्रतिबिंबित करने के लिए अच्छा अभ्यास होगा। मुझे अभी यह समस्या आ रही है।
रॉल्फ

मुझे लगता है कि कई कॉलम कुंजियां मेरी पिछली टिप्पणी में समस्या के साथ मदद कर सकती हैं ... अभी देख रही हूं।
रॉल्फ

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

पूर्ण विवरण और कार्यान्वयन विवरण के लिए इस उत्तर की जाँच करें
प्रदर्शन

एक विशिष्ट आईडी वाला कर्मचारी 'से' या 'एसएन' कैसे जाने?
म्हारासली

22

आप शायद दो विदेशी कुंजी बाधाओं को जोड़ सकते हैं (ईमानदारी से: मैंने कभी इसकी कोशिश नहीं की है), लेकिन यह तब माता-पिता को दोनों तालिकाओं में मौजूद होने पर जोर देगा।

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

                 employee       
employees_ce     ————————       employees_sn
————————————     type           ————————————
empid —————————> empid <——————— empid
name               /|\          name
                    |  
                    |  
      deductions    |  
      ——————————    |  
      empid ————————+  
      name

typeकर्मचारी तालिका में ceया होगा sn


मैंने कई विदेशी कुंजियों को जोड़ने की कोशिश की, उन्होंने काम किया, लेकिन एक रिकॉर्ड जोड़ते समय, जावा डर्बी मुझे बताता है कि दोनों विदेशी कुंजी बाधाओं का उल्लंघन किया गया है!

मैंने अभी इसे PostgreSQL पर आज़माया, और यह वहाँ काम करता है। क्या आपके पास दोनों तालिकाओं में मूल रिकॉर्ड है?
derobert

माता-पिता का रिकॉर्ड आपके कहने का मतलब है, साम्राज्य?

निश्चित रूप से समस्या को "कटौती" तालिका से "कर्मचारी" तालिका में स्थानांतरित कर दिया गया है। आप एक प्रकार के आधार पर संभावित अलग-अलग संस्थाओं का संदर्भ कैसे देंगे?
गॉपरट्रॉन

1
@gawpertron: खैर, साम्राज्य सभी प्रकार के लिए अद्वितीय है। आप किस प्रकार की तालिका को देखना चाहते हैं, यह देखने के लिए आप 'टाइप' फ़ील्ड का उपयोग कर सकते हैं। या सिर्फ LEFT JOINउन सभी को, अगर कुछ पर्याप्त हैं। जब 'कर्मचारी' आधार तालिका का उपयोग नहीं किया जाता है, तो प्राथमिक कुंजी घोषित नहीं की जा सकती है (क्योंकि यह तालिका या टेबलबी या ... संदर्भित हो रही है); अब यह हो सकता है। बंटवारे का ज्ञान employees_ceऔर employees_snग्रहण किया गया था, और उस धारणा को नोट किया गया है।
व्युत्पन्न

19

दरअसल मैं खुद ऐसा करता हूं। मेरे पास 'टिप्पणियां' नामक एक तालिका है जिसमें 3 अन्य तालिकाओं में रिकॉर्ड के लिए टिप्पणियां हैं। न तो समाधान वास्तव में सब कुछ संभालता है जिसे आप शायद चाहते हैं। आपके मामले में, आप ऐसा करेंगे:

समाधान 1:

  1. कर्मचारियों के लिए एक छोटे से क्षेत्र को जोड़ें_ कर्मचारी और कर्मचारी_ जिसमें एक डिफ़ॉल्ट मान है जो प्रत्येक तालिका में अलग है (यह फ़ील्ड एक 'तालिका पहचानकर्ता' का प्रतिनिधित्व करती है, इसलिए हम उन्हें tid_ce & tid_sn कहेंगे)

  2. तालिका के पीके और तालिका आईडी फ़ील्ड का उपयोग करके प्रत्येक तालिका पर एक अद्वितीय सूचकांक बनाएं।

  3. विदेशी कुंजी (तालिका आईडी) की दूसरी छमाही को संग्रहीत करने के लिए अपनी 'कटौती' तालिका में एक छोटे क्षेत्र को जोड़ें

  4. अपनी 'Deductions' तालिका में 2 विदेशी कुंजियाँ बनाएँ (आप संदर्भात्मक अखंडता को लागू नहीं कर सकते, क्योंकि या तो एक कुंजी मान्य होगी या दूसरी ... लेकिन दोनों कभी नहीं:

    ALTER TABLE [dbo].[Deductions]  WITH NOCHECK ADD  CONSTRAINT [FK_Deductions_employees_ce] FOREIGN KEY([id], [fk_tid])
    REFERENCES [dbo].[employees_ce] ([empid], [tid])
    NOT FOR REPLICATION 
    GO
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_ce]
    GO
    ALTER TABLE [dbo].[Deductions]  WITH NOCHECK ADD  CONSTRAINT [FK_Deductions_employees_sn] FOREIGN KEY([id], [fk_tid])
    REFERENCES [dbo].[employees_sn] ([empid], [tid])
    NOT FOR REPLICATION 
    GO
    ALTER TABLE [dbo].[Deductions] NOCHECK CONSTRAINT [FK_600_WorkComments_employees_sn]
    GO
    
    employees_ce
    --------------
    empid    name     tid
    khce1   prince    1
    
    employees_sn
    ----------------
    empid    name     tid 
    khsn1   princess  2
    
    deductions
    ----------------------
    id      tid       name  
    khce1   1         gold
    khsn1   2         silver         
    ** id + tid creates a unique index **
    

समाधान 2: यह समाधान संदर्भात्मक अखंडता को बनाए रखने की अनुमति देता है: 1. 'कटौती' तालिका में एक दूसरा विदेशी कुंजी फ़ील्ड बनाएं, दोनों विदेशी कुंजियों में अशक्त मानों की अनुमति दें, और सामान्य विदेशी कुंजी बनाएं:

    employees_ce
    --------------
    empid   name
    khce1   prince 

    employees_sn
    ----------------
    empid   name     
    khsn1   princess 

    deductions
    ----------------------
    idce    idsn      name  
    khce1   *NULL*    gold
    *NULL*  khsn1     silver         

अखंडता की केवल जाँच की जाती है यदि स्तंभ शून्य नहीं है, तो आप संदर्भात्मक अखंडता बनाए रख सकते हैं।


6

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

Table 1 Fruit
pk_fruitid, name
1, apple
2, pear

Table 2 Meat
Pk_meatid, name
1, beef
2, chicken

Table 3 Entity's
PK_entityid, anme
1, fruit
2, meat
3, desert

Table 4 Basket (Table using fk_s)
PK_basketid, fk_entityid, pseudo_entityrow
1, 2, 2 (Chicken - entity denotes meat table, pseudokey denotes row in indictaed table)
2, 1, 1 (Apple)
3, 1, 2 (pear)
4, 3, 1 (cheesecake)

SO Op का उदाहरण इस तरह दिखेगा

deductions
--------------
type    id      name
1      khce1   gold
2      khsn1   silver

types
---------------------
1 employees_ce
2 employees_sn

1

तकनीकी रूप से संभव है। आप शायद कटौती और कर्मचारी_एसएन में कर्मचारियों_के संदर्भ देंगे। लेकिन आप कर्मचारियों के कर्मचारियों और कर्मचारियों को क्यों नहीं मिलाते हैं? मेरे पास कोई कारण नहीं है कि आपके पास दो टेबल क्यों हैं। कई रिश्ते में कोई नहीं। और (इस उदाहरण में नहीं) कई कॉलम।

यदि आप एक कॉलम के लिए दो संदर्भ करते हैं, तो एक कर्मचारी के पास दोनों तालिकाओं में एक प्रविष्टि होनी चाहिए


1

हाँ यह संभव है। आपको 3 तालिका के लिए 2 एफके परिभाषित करने की आवश्यकता होगी। प्रत्येक FK एक तालिका के आवश्यक क्षेत्र (ओं) की ओर इशारा करता है (यानी विदेशी तालिका प्रति 1 FK)।


0

मान लें कि आपके पास किसी कारण के लिए दो कर्मचारी प्रकारों के लिए दो तालिकाओं होना चाहिए, मैं vmarquez के उत्तर पर विस्तार करूंगा:

स्कीमा:

employees_ce (id, name)
employees_sn (id, name)
deductions (id, parentId, parentType, name)

कटौती में डेटा:

deductions table
id      parentId      parentType      name
1       1             ce              gold
2       1             sn              silver
3       2             sn              wood
...

यह आपको अपने स्कीमा में किसी अन्य तालिका में कटौती बिंदु देने की अनुमति देगा। इस तरह का संबंध डेटाबेस-स्तर की बाधाओं, IIRC द्वारा समर्थित नहीं है, इसलिए आपको यह सुनिश्चित करना होगा कि आपका ऐप सही तरीके से बाधा का प्रबंधन करता है (जो कि एक ही डेटाबेस को मारते हुए कई अलग-अलग ऐप / सेवाओं के होने पर आपको अधिक बोझिल बना देता है)।

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