आप जो वर्णन कर रहे हैं उसे पॉलिमॉर्फिक एसोसिएशन कहा जाता है। यही है, "विदेशी कुंजी" कॉलम में एक आईडी मान होता है जो लक्ष्य तालिकाओं के एक सेट में मौजूद होना चाहिए। आमतौर पर लक्ष्य तालिका किसी तरह से संबंधित होती है, जैसे कि डेटा के कुछ सामान्य सुपरक्लास के उदाहरण। आपको विदेशी कुंजी कॉलम के साथ एक और कॉलम की भी आवश्यकता होगी, ताकि प्रत्येक पंक्ति पर, आप यह निर्दिष्ट कर सकें कि कौन सी लक्ष्य तालिका संदर्भित है।
CREATE TABLE popular_places (
user_id INT NOT NULL,
place_id INT NOT NULL,
place_type VARCHAR(10) -- either 'states' or 'countries'
-- foreign key is not possible
);
SQL बाधाओं का उपयोग करके पॉलीमॉर्फिक एसोसिएशन को मॉडल करने का कोई तरीका नहीं है। एक विदेशी कुंजी बाधा हमेशा एक लक्ष्य तालिका का संदर्भ देती है ।
पॉलीमॉर्फिक एसोसिएशन को रेल और हाइबरनेट जैसे फ्रेमवर्क द्वारा समर्थित किया जाता है। लेकिन वे स्पष्ट रूप से कहते हैं कि आपको इस सुविधा का उपयोग करने के लिए SQL बाधाओं को अक्षम करना होगा। इसके बजाय, आवेदन या रूपरेखा को यह सुनिश्चित करने के लिए समतुल्य कार्य करना चाहिए कि संदर्भ संतुष्ट है। यही है, विदेशी कुंजी में मूल्य संभव लक्ष्य तालिकाओं में से एक में मौजूद है।
डेटाबेस स्थिरता को लागू करने के संबंध में पॉलीमॉर्फिक एसोसिएशन कमजोर हैं। डेटा अखंडता लागू करने वाले सभी ग्राहकों पर निर्भर करता है जो डेटाबेस को एक ही संदर्भात्मक अखंडता तर्क के साथ लागू करते हैं, और प्रवर्तन बग मुक्त होना चाहिए।
यहां कुछ वैकल्पिक समाधान दिए गए हैं जो डेटाबेस-लागू संदर्भात्मक अखंडता का लाभ उठाते हैं:
प्रति लक्ष्य एक अतिरिक्त तालिका बनाएं। उदाहरण के लिए popular_states
और popular_countries
, जो संदर्भ states
और countries
क्रमशः। इन "लोकप्रिय" तालिकाओं में से प्रत्येक उपयोगकर्ता की प्रोफ़ाइल को भी संदर्भित करता है।
CREATE TABLE popular_states (
state_id INT NOT NULL,
user_id INT NOT NULL,
PRIMARY KEY(state_id, user_id),
FOREIGN KEY (state_id) REFERENCES states(state_id),
FOREIGN KEY (user_id) REFERENCES users(user_id),
);
CREATE TABLE popular_countries (
country_id INT NOT NULL,
user_id INT NOT NULL,
PRIMARY KEY(country_id, user_id),
FOREIGN KEY (country_id) REFERENCES countries(country_id),
FOREIGN KEY (user_id) REFERENCES users(user_id),
);
इसका मतलब यह है कि उपयोगकर्ता के सभी पसंदीदा पसंदीदा स्थानों को प्राप्त करने के लिए आपको इन दोनों तालिकाओं को क्वेरी करने की आवश्यकता है। लेकिन इसका मतलब है कि आप निरंतरता को लागू करने के लिए डेटाबेस पर भरोसा कर सकते हैं।
places
सुपरटेबल के रूप में एक टेबल बनाएं । जैसा कि अबी का उल्लेख है, एक दूसरा विकल्प यह है कि आपके लोकप्रिय स्थान एक तालिका का संदर्भ देते हैं places
, जो दोनों के लिए एक माता-पिता है states
और countries
। यही है, दोनों राज्यों और देशों के पास एक विदेशी कुंजी भी है places
(आप इस विदेशी कुंजी को प्राथमिक कुंजी भी बना सकते हैं states
और countries
)।
CREATE TABLE popular_areas (
user_id INT NOT NULL,
place_id INT NOT NULL,
PRIMARY KEY (user_id, place_id),
FOREIGN KEY (place_id) REFERENCES places(place_id)
);
CREATE TABLE states (
state_id INT NOT NULL PRIMARY KEY,
FOREIGN KEY (state_id) REFERENCES places(place_id)
);
CREATE TABLE countries (
country_id INT NOT NULL PRIMARY KEY,
FOREIGN KEY (country_id) REFERENCES places(place_id)
);
दो कॉलम का उपयोग करें। एक स्तंभ के बजाय जो दो लक्ष्य तालिकाओं का संदर्भ दे सकता है, दो स्तंभों का उपयोग करें। ये दो स्तंभ हो सकते हैं NULL
; वास्तव में उनमें से केवल एक गैर होना चाहिए NULL
।
CREATE TABLE popular_areas (
place_id SERIAL PRIMARY KEY,
user_id INT NOT NULL,
state_id INT,
country_id INT,
CONSTRAINT UNIQUE (user_id, state_id, country_id), -- UNIQUE permits NULLs
CONSTRAINT CHECK (state_id IS NOT NULL OR country_id IS NOT NULL),
FOREIGN KEY (state_id) REFERENCES places(place_id),
FOREIGN KEY (country_id) REFERENCES places(place_id)
);
संबंधपरक सिद्धांत के संदर्भ में, पॉलीमॉर्फिक एसोसिएशन फर्स्ट नॉर्मल फॉर्म का उल्लंघन करता है , क्योंकि popular_place_id
यह दो अर्थों के साथ एक कॉलम है: यह या तो एक राज्य या एक देश है। आप एक व्यक्ति की दुकान नहीं होगा age
और उनके phone_number
एक एकल स्तंभ में, और एक ही कारण के लिए आप दोनों की दुकान नहीं करना चाहिए state_id
और country_id
एक एकल स्तंभ में। तथ्य यह है कि इन दो विशेषताओं में संगत डेटा प्रकार हैं संयोग; वे अभी भी विभिन्न तार्किक संस्थाओं का संकेत देते हैं।
पॉलीमॉर्फिक एसोसिएशंस भी थर्ड नॉर्मल फॉर्म का उल्लंघन करती हैं , क्योंकि कॉलम का अर्थ अतिरिक्त कॉलम पर निर्भर करता है, जिसमें उस टेबल का नाम होता है, जिस पर फॉरेन की का जिक्र होता है। थर्ड नॉर्मल फॉर्म में, एक टेबल में एक विशेषता केवल उस टेबल की प्राथमिक कुंजी पर निर्भर होना चाहिए।
@SavasVedova से पुनः टिप्पणी करें:
मुझे यकीन नहीं है कि मैं टेबल की परिभाषा या एक उदाहरण के प्रश्न को देखे बिना आपके विवरण का अनुसरण करता हूं, लेकिन ऐसा लगता है कि आपके पास बस एक से अधिक Filters
टेबल हैं, प्रत्येक में एक विदेशी कुंजी है जो एक केंद्रीय Products
तालिका का संदर्भ देती है ।
CREATE TABLE Products (
product_id INT PRIMARY KEY
);
CREATE TABLE FiltersType1 (
filter_id INT PRIMARY KEY,
product_id INT NOT NULL,
FOREIGN KEY (product_id) REFERENCES Products(product_id)
);
CREATE TABLE FiltersType2 (
filter_id INT PRIMARY KEY,
product_id INT NOT NULL,
FOREIGN KEY (product_id) REFERENCES Products(product_id)
);
...and other filter tables...
उत्पादों को एक विशेष प्रकार के फ़िल्टर में शामिल करना आसान है यदि आप जानते हैं कि आप किस प्रकार से जुड़ना चाहते हैं:
SELECT * FROM Products
INNER JOIN FiltersType2 USING (product_id)
यदि आप चाहते हैं कि फ़िल्टर प्रकार गतिशील हो, तो आपको SQL क्वेरी बनाने के लिए एप्लिकेशन कोड लिखना होगा। एसक्यूएल की आवश्यकता है कि आप जिस समय क्वेरी लिखते हैं उस समय तालिका निर्दिष्ट और तय की जाए। आप व्यक्तिगत रूप से अलग-अलग पंक्तियों में पाए गए मूल्यों के आधार पर सम्मिलित तालिका को गतिशील रूप से नहीं चुन सकते हैं Products
।
केवल अन्य विकल्प बाहरी जोड़ का उपयोग करके सभी फ़िल्टर टेबल में शामिल होना है। जिनके पास कोई मेल नहीं है product_id बस नल की एक पंक्ति के रूप में वापस आ जाएगी। लेकिन आपको अभी भी सभी सम्मिलित तालिकाओं को हार्डकोड करना होगा, और यदि आप नए फ़िल्टर टेबल जोड़ते हैं, तो आपको अपना कोड अपडेट करना होगा।
SELECT * FROM Products
LEFT OUTER JOIN FiltersType1 USING (product_id)
LEFT OUTER JOIN FiltersType2 USING (product_id)
LEFT OUTER JOIN FiltersType3 USING (product_id)
...
सभी फ़िल्टर टेबल से जुड़ने का एक और तरीका यह है कि इसे क्रमबद्ध तरीके से करें:
SELECT * FROM Product
INNER JOIN FiltersType1 USING (product_id)
UNION ALL
SELECT * FROM Products
INNER JOIN FiltersType2 USING (product_id)
UNION ALL
SELECT * FROM Products
INNER JOIN FiltersType3 USING (product_id)
...
लेकिन इस प्रारूप में अभी भी आपको सभी तालिकाओं के संदर्भ लिखने की आवश्यकता है। आसपास कोई नहीं मिल रहा है।
join
लक्ष्य भी बदल जाएगा ...... क्या मैं बहुत अधिक या क्या कर रहा हूं? मदद!