2009-03-21 12 views
81

मुझे डेटाबेस कर्मचारियों के तहत कर्मचारी_से और कर्मचारी_एसएन दो टेबल हैं।विदेशी कुंजी एकाधिक तालिकाओं में प्राथमिक कुंजी का जिक्र करती है?

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

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

उदाहरण के लिए

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

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

तो यह संभव है?

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

उत्तर

2

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

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

1

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

21

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

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

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

कर्मचारी तालिका में typece या sn होगा। अपने डेटाबेस की एक उच्च स्तर के वर्णन से

प्रारंभ:

+0

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

+0

मैंने अभी पोस्टग्रेएसक्यूएल पर कोशिश की, और यह वहां काम करता है। क्या आपके पास दोनों टेबलों में अभिभावक रिकॉर्ड है? – derobert

+0

अभिभावक रिकॉर्ड आप कहने का मतलब है, एम्पाइड? –

87

यह मानते हुए कि मैं अपने परिदृश्य को सही ढंग से समझ लिया है, यह क्या मैं सही तरीका यह है कहेंगे है! आपके पास कर्मचारी हैं, और कर्मचारी "सीई" कर्मचारी और "स्न" कर्मचारी (जो कुछ भी हैं) हो सकते हैं। ऑब्जेक्ट उन्मुख शर्तों में, "सीई कर्मचारी" और "एसएन कर्मचारी" नामक दो उप-वर्गों के साथ एक वर्ग "कर्मचारी" होता है। 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.idemployees.id पर एक विदेशी कुंजी है, जैसे employees_sn.id है।

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

+12

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

+0

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

+12

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

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

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

15

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

समाधान 1:

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

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

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

  4. अपने 'कटौती' तालिका में 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: यह समाधान रेफेरेंन्शिअल सत्यनिष्ठा मा होने की अनुमति देता intained: 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) 

अतः Op के उदाहरण की तरह लग रहे हैं इस

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

types 
--------------------- 
1 employees_ce 
2 employees_sn 
संबंधित मुद्दे