FK बाधाओं के लिए नियम
शीर्षक में और अपने पाठ के अंत में प्रश्न का उत्तर देने के लिए:
"मैं अब भी जानना चाहूंगा कि कैसे एक विदेशी कुंजी दो प्राथमिक कुंजियों को संदर्भित करती है।"
यह असंभव है।
-
एक
FOREIGN KEY
बाधा केवल एक . को इंगित कर सकती है तालिका और प्रत्येक तालिका में केवल एक हो सकता हैPRIMARY KEY
कोड> बाधा। -
या आपके पास एकाधिक हो सकता है
FOREIGN KEY
एक . को संदर्भित करने वाले एक ही कॉलम पर बाधाएंPRIMARY KEY
प्रत्येक (अलग) तालिका का। (शायद ही कभी उपयोगी।)
हालांकि , एक एकल PK या FK कर सकते हैं कई कॉलमों को फैलाना।
और एक FK लक्ष्य में किसी भी स्पष्ट रूप से परिभाषित अद्वितीय (सेट) कॉलम को संदर्भित कर सकता है, न कि केवल PK को। मैनुअल:
एक बहुस्तंभ PK या UNIQUE
बाधा को केवल मेल खाने वाले कॉलम प्रकारों के साथ एक बहु-स्तंभ FK बाधा द्वारा संदर्भित किया जा सकता है।
आप क्या पूछते हैं
चूंकि इसे UNIQUE
की कॉलम सूची में एक ही कॉलम को एक से अधिक बार उपयोग करने की अनुमति नहीं है या PRIMARY KEY
बाधा, एक FOREIGN KEY
की लक्ष्य सूची एक ही कॉलम का एक से अधिक बार उपयोग भी नहीं कर सकते हैं। लेकिन हमें स्रोत . में एक ही कॉलम को एक से अधिक बार उपयोग करने से रोकने के लिए कुछ भी नहीं है सूची। आप जो पूछ रहे हैं उसे लागू करने की क्षमता यहां निहित है (लेकिन शायद इसका मतलब यह नहीं था):
"team_statistics
में तालिका team_statistics.team_id
एक विदेशी कुंजी होनी चाहिए जो matches.team_id
. का संदर्भ देती हो और matches.team_id1
"
(team_id, team_id1)
. का संयोजन तालिका में matches
परिभाषित करने की आवश्यकता होगी UNIQUE
. team_statistics.team_id
. में मान team = team1
वाले मामलों तक ही सीमित रहेगा तालिका में matches
तार्किक परिणाम के रूप में:
ALTER TABLE matches
ADD constraint matches_teams_groups_uni UNIQUE (team_id, team_id1);
ALTER TABLE team_statistics
ADD constraint team_statistics_team_group fkey
FOREIGN KEY (team_id, team_id) -- same column twice!
REFERENCES matches(team_id, team_id1);
यहां तक कि कुछ सेटअप के लिए भी सही हो सकता है, लेकिन आपके लिए नहीं।
शायद आपको क्या चाहिए
मेरा शिक्षित अनुमान है कि आप कुछ इस तरह चाहते हैं:
(match_id, team_id)
तालिका में team_statistics
एक विदेशी कुंजी होनी चाहिए जो या तो references का संदर्भ देती हो (match_id, team_id)
या (match_id, team_id1)
तालिका में matches
.
और यह एफके बाधाओं और सिर्फ दो तालिकाओं के साथ संभव नहीं है। आप कर सकते थे एक CHECK
का दुरुपयोग करें एक नकली IMMUTABLE
. के साथ बाधा कार्य करें और इसे NOT VALID
make बनाएं . इस उत्तर में अध्याय "चेक बाधा के साथ सस्ता" देखें:
लेकिन यह उन्नत चालबाजी और कम विश्वसनीय है। यहां मेरा सुझाव नहीं है, इसलिए मैं विस्तार से नहीं बता रहा हूं। मेरा सुझाव है कि सामान्य करें आपकी स्कीमा उपयोगी तरीके से, जैसे:
CREATE TABLE team (team_id serial PRIMARY KEY
, team text NOT NULL UNIQUE); -- add more attributes for team
CREATE TABLE match (match_id serial PRIMARY KEY); -- add more attributes for match
CREATE TABLE match_team (
match_id int REFERENCES match -- short notation for FK
, team_id int REFERENCES team
, home boolean -- TRUE for home team, FALSE for away team
, innings_score int
-- more attributes of your original "team_statistics"
, PRIMARY KEY (match_id, team_id, home) -- !!! (1st column = match_id)
, UNIQUE (team_id, match_id) -- optional, (1st column = team_id)
);
home
मैच की घरेलू टीम को चिह्नित करता है, लेकिन पीके में शामिल करके, प्रति मैच अधिकतम दो टीमों तक भी सीमित कर देता है . (पीके कॉलम परिभाषित हैं NOT NULL
परोक्ष रूप से।)
वैकल्पिक UNIQUE
(team_id, match_id)
. पर प्रतिबंध टीमों को अपने खिलाफ खेलने से रोकता है। इंडेक्स कॉलम के उल्टे अनुक्रम का उपयोग करके (नियम लागू करने के लिए अप्रासंगिक) यह पीके के लिए एक इंडेक्स पूरक भी प्रदान करता है, जो आमतौर पर उपयोगी भी होता है। देखें:
आप कर सकते थे एक अलग match_team_statistics
add जोड़ें , लेकिन यह match_team
. के लिए केवल एक वैकल्पिक 1:1 एक्सटेंशन होगा अभी व। वैकल्पिक रूप से बस match_team
में कॉलम जोड़ें ।
मैं दृश्य जोड़ सकता हूं विशिष्ट प्रदर्शनों के लिए, जैसे:
CREATE VIEW match_result AS
SELECT m.match_id
, concat_ws(' : ', t1.team, t2.team) AS home_vs_away_team
, concat_ws(' : ', mt1.innings_score, mt2.innings_score) AS result
FROM match m
LEFT JOIN match_team mt1 ON mt1.match_id = m.match_id AND mt1.home
LEFT JOIN team t1 ON t1.team_id = mt1.team_id
LEFT JOIN match_team mt2 ON mt2.match_id = m.match_id AND NOT mt2.home
LEFT JOIN team t2 ON t2.team_id = mt2.team_id;
बुनियादी सलाह: