44

मेरे पास है मेरे एप्लिकेशन में 'टिप्पणी' तालिका निम्नलिखित:MySQL - सशर्त विदेशी कुंजी प्रतिबन्ध

comments 
-------- 
id   INT 
foreign_id INT 
model  TEXT 
comment_text TEXT 
... 

इस तालिका के विचार मेरे ऐप के विभिन्न भागों के लिए टिप्पणियों स्टोर करने के लिए है - यह ब्लॉग पोस्ट के लिए टिप्पणी स्टोर कर सकते हैं अर्थात्:

1|34|blogpost|lorem ipsum... 

उपयोगकर्ता चित्र:

2|12|picture|lorem ipsum... 

और इतने पर।

अब, ऐसे डेटा पर विदेशी कुंजी बाधा को मजबूर करने का कोई तरीका है? टिप्पणियाँ तालिका में इस तरह

अर्थात कुछ:

FOREIGN KEY (`foreign_id`) REFERENCES blogposts (`id`) 
//but only when model='blogpost' 

उत्तर

71

आप एक डिजाइन कि बहुरूपी संघों कहा जाता है क्या करने की कोशिश कर रहे हैं। यही है, विदेशी कुंजी कई संबंधित तालिकाओं में पंक्तियों का संदर्भ दे सकती है।

लेकिन एक विदेशी कुंजी बाधा को बिल्कुल एक तालिका का संदर्भ देना चाहिए। आप अपनी Comments तालिका के किसी अन्य कॉलम में मान के आधार पर एक विदेशी कुंजी घोषित नहीं कर सकते हैं जो अलग-अलग तालिकाओं का संदर्भ देता है। यह संबंधपरक डेटाबेस डिजाइन के कई नियमों का उल्लंघन करेगा।

एक बेहतर समाधान यह है कि टिप्पणियों द्वारा संदर्भित "सुपरटेबल" का एक प्रकार बनाना है।

CREATE TABLE Commentable (
    id SERIAL PRIMARY KEY 
); 

CREATE TABLE Comments (
    comment_id SERIAL PRIMARY KEY, 
    foreign_id INT NOT NULL, 
    ... 
    FOREIGN KEY (foreign_id) REFERENCES Commentable(id) 
); 

आपके प्रत्येक सामग्री प्रकार को इस प्रख्यात उप-प्रकार माना जाएगा। यह इंटरफ़ेस की ऑब्जेक्ट उन्मुख अवधारणा के समान है।

CREATE TABLE BlogPosts (
    blogpost_id INT PRIMARY KEY, -- notice this is not auto-generated 
    ... 
    FOREIGN KEY (blogpost_id) REFERENCES Commentable(id) 
); 

CREATE TABLE UserPictures (
    userpicture_id INT PRIMARY KEY, -- notice this is not auto-generated 
    ... 
    FOREIGN KEY (userpicture_id) REFERENCES Commentable(id) 
); 

इससे पहले कि आप BlogPosts या UserPictures में एक पंक्ति सम्मिलित कर सकते हैं, आप एक नया pseudokey आईडी उत्पन्न करने के लिए Commentable करने के लिए एक नई पंक्ति सम्मिलित करना होगा। फिर आप उस जेनरेट आईडी का उपयोग कर सकते हैं जब आप संबंधित उप प्रकार तालिका में सामग्री डालते हैं।

एक बार जब आप ऐसा करते हैं, तो आप रेफरेंसियल अखंडता बाधाओं पर भरोसा कर सकते हैं।

+1

मुझे लगता है कि उपयोगकर्ता चित्रों में एक फ़ील्ड user_id है जो उपयोगकर्ता तालिका का संदर्भ देता है। आप इस तरह से उपयोगकर्ता को कैसे हटाते हैं कि डिलीट टिप्पणी योग्य तालिका में कैस्केड होगा? मैंने यहां इस प्रश्न से पूछा है - http://stackoverflow.com/questions/11497149/how-to-enforce-referential-integrity-on-single-table-heheritance - और अगर आप यह समझा सकते हैं कि आप इसे कैसे संभालेंगे तो आभारी होंगे हिचकी मैं फंस रहा हूँ। –

+13

@MattMcCormick, मैं अब SO पर प्रश्नों का उत्तर नहीं देता, क्योंकि अप्रिय मॉडरेटर ने इसे भाग लेने के लिए अपरिवर्तनीय बना दिया है। –

+2

ओह ठीक है। आपकी पिछली भागीदारी के लिए धन्यवाद। मैंने सिंगल टेबल विरासत और पॉलिमॉर्फिक एसोसिएशन के संबंध में आपके कुछ जवाब पढ़े और आपकी बातचीत से स्लाइड्स को भी देखा जो आपने उनमें से एक में संदर्भित किया था। इससे मुझे डेटाबेस के साथ स्थितियों की बेहतर पहचान करने में मदद मिली जो सड़क से समस्या का कारण बन सकती है। मैंने अपनी पुस्तक को मेरी रीडिंग सूची में जोड़ा है और शायद इसे पढ़ने के लिए मेरी अगली सॉफ्टवेयर पुस्तक के लिए इसे उठाएगा। –

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