13

मैं single table inheritance के बारे में Bill Karwin's कुछ उत्तर पढ़ सकते हैं और लगता है कि इस दृष्टिकोण सेटअप मैं विचार कर रहा हूँ के लिए अच्छा होगा है:सिंगल टेबल विरासत पर रेफरेंसियल अखंडता को कैसे लागू किया जाए?

Playlist 
-------- 
id AUTO_INCREMENT 
title 

TeamPlaylist 
------------ 
id REFERENCES Playlist.id 
teamId REFERENCES Team.id 

UserPlaylist 
------------ 
id REFERENCES Playlist.id 
userId REFERENCES User.id 

PlaylistVideo 
------------- 
id 
playlistId REFERENCES Playlist.id 
videoId REFERENCES Video.id 

सभी CASCADE विकल्पों DELETE की तैयारी में हैं जो सही ढंग से जब एक Playlist है के लिए काम करेंगे हटा दिया गया है, हालांकि, क्या होता है यदि User या Team हटा दिया गया है?

यानी। यदि User हटा दिया गया है, तो UserPlaylist में पंक्तियां हटा दी जाएंगी लेकिन Playlist और PlaylistVideo में संदर्भित पंक्तियां बनी रहेंगी। मैंने इसे TRIGGER AFTER DELETE के रूप में लागू करने के बारे में सोचा था, लेकिन यह जानने का कोई तरीका नहीं है कि डिलीट अनुरोध आया था क्योंकि Playlist हटा दिया गया था या User हटा दिया गया था।

इस स्थिति में अखंडता को लागू करने का सबसे अच्छा तरीका क्या है?

संपादित करें (बशर्ते ERD)

enter image description here

+1

मुझे समझ में नहीं आता कि उपयोगकर्ता प्लेलिस्ट प्लेलिस्ट का विरासत कैसे हो सकता है। क्या यह इसके बजाय संबंध तालिका नहीं होनी चाहिए? – Sebas

+0

मुझे आपका प्रश्न नहीं समझ रहा है। उपयोगकर्ता प्लेलिस्ट प्लेलिस्ट से संबंधित है कि आईडी प्लेलिस्ट.आईडी से आता है। सिंगल टेबल विरासत के बारे में कुछ और प्रश्न यहां दिए गए हैं - http://stackoverflow.com/a/3383320/47278 –

+0

पूरे कारण से आप नहीं चाहते कि उपयोगकर्ता प्लेलिस्ट और प्लेलिस्ट वीडियो पंक्तियों को निकालने के लिए हटा दिया जाए क्योंकि वे भी संदर्भित हो सकते हैं अन्य उपयोगकर्ताप्लेलिस्ट या टीमप्लेलिस्ट रिकॉर्ड द्वारा। – WebChemist

उत्तर

3

मेरी नजर में, समस्या यह है कि आपके User और Team तालिकाओं जो कि एक महाप्रकार तालिका (Party इस तरह के रूप में), नहीं प्लेलिस्ट टेबल होना चाहिए रहे हैं।

जैसा कि आपने बताया है, प्लेलिस्ट पर अपनी "टेबल विरासत" करने से जुर्माना आता है जब पता लगाना है कि क्या हटाना है। जब आप विरासत को उपयोगकर्ता/टीम स्तर पर ले जाते हैं तो ये सभी समस्याएं दूर हो जाती हैं।

आप this answer for more detail about supertyping/subtyping देख सकते हैं।

मुझे कोड की आपूर्ति करने के लिए खेद है क्योंकि मुझे दिल से MySQL वाक्यविन्यास नहीं पता है।

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

अपने डेटाबेस में, केवल Playlist तालिका को FK से Party (PartyID) पर रखने के द्वारा, आपने ट्रिगर्स के बिना डेटाबेस स्तर पर आसानी से अपने व्यवसाय नियम को लागू किया है।

+0

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

+0

यही सबटाइप टेबल है: वे जिस तरीके से अलग हैं। बदलने में वास्तविक समस्या बाधाओं को छोड़ने और पुनर्निर्माण के साथ, सेटों में से किसी एक के लिए आईडी अपडेट कर रही है। लेकिन मुझे लगता है कि यह सार्थक है। :) – ErikE

+0

मेरा जवाब चुनने के लिए धन्यवाद! आपको यह तय करने का क्या कारण था कि यह रास्ता तय करना था? – ErikE

4

ठीक मैं देख रहा हूँ तुम यहाँ क्या चाहते हैं ... आप क्या करना चाहते क्या या तो एक पंक्ति है के बाद की तरह

DELETE FROM playlist 
WHERE  id 
NOT IN  (
    SELECT id 
    FROM UserPlayList 
    UNION 
    SELECT id 
    FROM TeamPlayList 
) 

एक प्रश्न चलाया जाता है उपयोगकर्ताओं या टीमों से हटाए गए

11

आप क्या कर सकते हैं अपने Users और Team टेबल पर ट्रिगर्स को कार्यान्वित करना है जो निष्पादित करता है उटे जब भी पंक्तियों से हटा दिया जाता है या तो:

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

DELIMITER $$ 
CREATE TRIGGER user_playlist_delete 
BEFORE DELETE ON User FOR EACH ROW 
BEGIN 
    DELETE a FROM Playlist a 
    INNER JOIN UserPlaylist b ON a.id = b.id AND b.userId = OLD.id; 
END$$ 
DELIMITER ; 

टीम तालिका:

DELIMITER $$ 
CREATE TRIGGER team_playlist_delete 
BEFORE DELETE ON Team FOR EACH ROW 
BEGIN 
    DELETE a FROM Playlist a 
    INNER JOIN TeamPlaylist b ON a.id = b.id AND b.teamId = OLD.id; 
END$$ 
DELIMITER ; 

क्या इन ट्रिगर्स क्या करेंगे हर बार एक रिकॉर्ड एक से हटा दिया जाता है इन तालिकाओं में से DELETE ऑपरेशन स्वचालित रूप से Playlists तालिका पर id का उपयोग कर निष्पादित हो जाएगा जो हटाए जाने वाले हैं (एक आंतरिक शामिल होने के माध्यम से)।

मैंने इसका परीक्षण किया है और यह बहुत अच्छा काम करता है।

+0

शानदार समाधान। इसे myslef का परीक्षण नहीं किया है, लेकिन ठोस लग रहा है।+1 – techtheatre

+0

अच्छा विचार जेन। किसी कारण से मैंने ट्रिगर को उपयोगकर्ता या टीम टेबल पर डालने के बारे में सोचा नहीं था - केवल उपयोगकर्ता प्लेलिस्ट या टीम प्लेलिस्ट टेबल। –

+0

मुझे नहीं लगता कि यह समस्या हल करने का सबसे अच्छा तरीका है ... – ErikE

1

जेन बिएन का जवाब काफी स्पष्ट & शानदार है। लेकिन मुझे ट्रिगर के उपयोग के बिना ऐसा करने का कोई विचार है क्योंकि ट्रिगर में कई समस्याएं हैं।

क्या आप किसी प्रोग्रामिंग भाषा का उपयोग कर रहे हैं? auto commit false

यदि हाँ तो,

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

अब अपने मुख्य कार्य के लिए एक और क्वेरी तैयार करें यानी उपयोगकर्ता को हटाएं, और उपयोगकर्ता प्लेलिस्ट में पंक्तियां स्वचालित रूप से हटा दी जाएंगी (CASCADE DELETE विकल्प के कारण)।अब अपनी दूसरी क्वेरी और commit चलाएं।

अंत में अपना लेनदेन auto commit true बनाएं।

यह सफलतापूर्वक काम कर रहा है, उम्मीद है कि यह सहायक होगा।

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