आपके वर्तमान डिज़ाइन को अनन्य आर्क्स . कहा जाता है जहां sets
तालिका में दो विदेशी कुंजी हैं, और उनमें से एक को गैर-शून्य होने की आवश्यकता है। यह बहुरूपी संघों को लागू करने का एक तरीका है, क्योंकि दी गई विदेशी कुंजी केवल एक लक्ष्य तालिका को संदर्भित कर सकती है।
एक अन्य समाधान एक सामान्य "सुपरटेबल" बनाना है जो दोनों users
और schools
संदर्भ, और फिर उसका उपयोग sets
. के पैरेंट के रूप में करें ।
create table set_owner
create table users
PK is also FK --> set_owner
create table schools
PK is also FK --> set_owner
create table sets
FK --> set_owner
आप इसे इंटरफ़ेस . के समान मान सकते हैं OO मॉडलिंग में:
interface SetOwner { ... }
class User implements SetOwner { ... }
class School implements SetOwner { ... }
class Set {
SetOwner owner;
}
अपनी टिप्पणी दें:
SetOwners तालिका को आईडी मान उत्पन्न करने दें। इससे पहले कि आप उपयोगकर्ताओं या स्कूलों में सम्मिलित कर सकें, आपको SetOwners में सम्मिलित करना होगा। तो उपयोगकर्ताओं और स्कूलों में आईडी बनाएं नहीं स्वत:वृद्धि; बस उस मान का उपयोग करें जो SetOwners द्वारा उत्पन्न किया गया था:
INSERT INTO SetOwners DEFAULT VALUES; -- generates an id
INSERT INTO Schools (id, name, location) VALUES (LAST_INSERT_ID(), 'name', 'location');
इस तरह किसी दिए गए आईडी मान का उपयोग स्कूल और उपयोगकर्ता दोनों के लिए नहीं किया जाएगा।
आप निश्चित रूप से ऐसा कर सकते हैं। वास्तव में, अन्य कॉलम भी हो सकते हैं जो उपयोगकर्ताओं और स्कूलों दोनों के लिए सामान्य हैं, और आप इन कॉलमों को सुपरटेबल सेटऑनर्स में रख सकते हैं। यह मार्टिन फाउलर के क्लास टेबल इनहेरिटेंस में आता है पैटर्न।
आपको एक जॉइन करना है। यदि आप किसी दिए गए सेट से क्वेरी कर रहे हैं और आप जानते हैं कि यह एक उपयोगकर्ता (स्कूल नहीं) का है, तो आप सेटऑनर्स में शामिल होना छोड़ सकते हैं और सीधे उपयोगकर्ताओं से जुड़ सकते हैं। जॉइन करने के लिए विदेशी चाबियों से जाना जरूरी नहीं है।
SELECT u.name FROM Sets s JOIN Users u ON s.SetOwner_id = u.id WHERE ...
यदि आप नहीं जानते कि दिया गया सेट किसी उपयोगकर्ता का है या स्कूल का, तो आपको दोनों के साथ बाहरी जुड़ाव करना होगा:
SELECT COALESCE(u.name, sc.name) AS name
FROM Sets s
LEFT OUTER JOIN Users u ON s.SetOwner_id = u.id
LEFT OUTER JOIN Schools sc ON s.SetOwner_id = sc.id
WHERE ...
आप जानते हैं कि SetOwner_id एक या दूसरी तालिका, उपयोगकर्ता या स्कूल से मेल खाना चाहिए, लेकिन दोनों नहीं।