यह एसक्यूएल में करना आसान नहीं है लेकिन यह असंभव नहीं है। यदि आप अकेले DDL के माध्यम से इसे लागू करना चाहते हैं, तो DBMS को DEFERRABLE
बाधाओं को लागू करना होगा । यह किया जा सकता है (और पोस्टग्रेज में काम करने के लिए जाँच की जा सकती है, जिसने उन्हें लागू किया है):
-- lets create first the 2 tables, A and B:
CREATE TABLE a
( aid INT NOT NULL,
bid INT NOT NULL,
CONSTRAINT a_pk PRIMARY KEY (aid)
);
CREATE TABLE b
( bid INT NOT NULL,
aid INT NOT NULL,
CONSTRAINT b_pk PRIMARY KEY (bid)
);
-- then table R:
CREATE TABLE r
( aid INT NOT NULL,
bid INT NOT NULL,
CONSTRAINT r_pk PRIMARY KEY (aid, bid),
CONSTRAINT a_r_fk FOREIGN KEY (aid) REFERENCES a,
CONSTRAINT b_r_fk FOREIGN KEY (bid) REFERENCES b
);
यहाँ तक "सामान्य" डिज़ाइन है, जहाँ हर A
व्यक्ति शून्य से संबंधित हो सकता है, एक या कई B
और हर B
शून्य, एक या कई से संबंधित हो सकता है A
।
"कुल भागीदारी" प्रतिबंध को उल्टे क्रम ( A
और B
क्रमशः, संदर्भित R
) में बाधाओं की आवश्यकता है । बीत रहा है FOREIGN KEY
(एक्स से Y के लिए और एक्स वाई से) एक चक्र (एक "चिकन और अंडे" समस्या) बना रहा है और उस के कारण है कि हम उनमें से एक कम से कम करने की आवश्यकता है विपरीत दिशाओं में कमी DEFERRABLE
। इस मामले में हमारे पास दो वृत्त हैं ( A -> R -> A
और B -> R -> B
इसलिए हमें दो अड़चन की आवश्यकता है:
-- then we add the 2 constraints that enforce the "total participation":
ALTER TABLE a
ADD CONSTRAINT r_a_fk FOREIGN KEY (aid, bid) REFERENCES r
DEFERRABLE INITIALLY DEFERRED ;
ALTER TABLE b
ADD CONSTRAINT r_b_fk FOREIGN KEY (aid, bid) REFERENCES r
DEFERRABLE INITIALLY DEFERRED ;
तब हम परीक्षण कर सकते हैं कि हम डेटा सम्मिलित कर सकते हैं। ध्यान दें कि INITIALLY DEFERRED
जरूरत नहीं है। हम बाधाओं को परिभाषित कर सकते थे, DEFERRABLE INITIALLY IMMEDIATE
लेकिन फिर हमें SET CONSTRAINTS
लेनदेन के दौरान उन्हें हटाने के लिए कथन का उपयोग करना होगा । हालांकि हर मामले में, हमें एक ही लेनदेन में तालिकाओं में सम्मिलित करने की आवश्यकता है:
-- insert data
BEGIN TRANSACTION ;
INSERT INTO a (aid, bid)
VALUES
(1, 1), (2, 5),
(3, 7), (4, 1) ;
INSERT INTO b (aid, bid)
VALUES
(1, 1), (1, 2),
(2, 3), (2, 4),
(2, 5), (3, 6),
(3, 7) ;
INSERT INTO r (aid, bid)
VALUES
(1, 1), (1, 2),
(2, 3), (2, 4),
(2, 5), (3, 6),
(3, 7), (4, 1),
(4, 2), (4, 7) ;
END ;
SQLfiddle पर परीक्षण किया गया ।
यदि DBMS में DEFERRABLE
बाधा नहीं है , तो एक वर्कअराउंड के रूप में A (bid)
और B (aid)
कॉलम को परिभाषित करना है NULL
। INSERT
प्रक्रियाओं / बयान तो में पहले डालने करना होगा A
और B
(में nulls डालने bid
और aid
क्रमशः), तो में डालने R
और उसके बाद से संबंधित रिक्त नहीं मूल्यों के ऊपर शून्य मान अद्यतन R
।
इस दृष्टिकोण के साथ, डीबीएमएस लागू नहीं करता है DDL द्वारा आवश्यकताओं अकेले लेकिन हर INSERT
(और UPDATE
और DELETE
और MERGE
) प्रक्रिया पर विचार किया जाएगा और तदनुसार समायोजित और उन का उपयोग करने के केवल उन्हें और नहीं तालिकाओं के लिए प्रत्यक्ष लेखन पहुँच है प्रतिबंधित किया जाना है है।
FOREIGN KEY
बाधाओं में हलकों का होना कई सर्वोत्तम अभ्यासों और अच्छे कारणों के लिए नहीं माना जाता है, जटिलता उनमें से एक है। उदाहरण के लिए दूसरे दृष्टिकोण के साथ (अशक्त स्तंभों के साथ), अद्यतन और हटाने वाली पंक्तियों को अभी भी अतिरिक्त कोड के साथ डीबीएमएस पर निर्भर रहना होगा। उदाहरण के लिए SQL सर्वर में, आप सिर्फ ON DELETE CASCADE
इसलिए नहीं डाल सकते क्योंकि FK सर्किल होने पर कैस्केडिंग अपडेट और डिलीट की अनुमति नहीं है।
कृपया इस संबंधित प्रश्न के उत्तर भी पढ़ें:
कैसे एक विशेषाधिकार प्राप्त बच्चे के साथ एक-से-कई संबंध हैं?
एक और, 3 जी दृष्टिकोण (उपर्युक्त प्रश्न में मेरा उत्तर देखें) परिपत्र FK को पूरी तरह से हटाने के लिए है। तो, कोड के पहले भाग में रखते हुए (टेबल के साथ A
, B
, R
और विदेशी कुंजी केवल आर से ए और बी के लिए) लगभग बरकरार (वास्तव में यह सरल बनाने), हम के लिए एक और तालिका जोड़ने A
से "होना आवश्यक है एक" संबंधित आइटम स्टोर करने के लिए B
। इसलिए, A (bid)
स्तंभ A_one (bid)
ए से बी के ए से रिवर्स रिलेशनशिप के लिए किया जाता है:
CREATE TABLE a
( aid INT NOT NULL,
CONSTRAINT a_pk PRIMARY KEY (aid)
);
CREATE TABLE b
( bid INT NOT NULL,
CONSTRAINT b_pk PRIMARY KEY (bid)
);
-- then table R:
CREATE TABLE r
( aid INT NOT NULL,
bid INT NOT NULL,
CONSTRAINT r_pk PRIMARY KEY (aid, bid),
CONSTRAINT a_r_fk FOREIGN KEY (aid) REFERENCES a,
CONSTRAINT b_r_fk FOREIGN KEY (bid) REFERENCES b
);
CREATE TABLE a_one
( aid INT NOT NULL,
bid INT NOT NULL,
CONSTRAINT a_one_pk PRIMARY KEY (aid),
CONSTRAINT r_a_fk FOREIGN KEY (aid, bid) REFERENCES r
);
CREATE TABLE b_one
( bid INT NOT NULL,
aid INT NOT NULL,
CONSTRAINT b_one_pk PRIMARY KEY (bid),
CONSTRAINT r_b_fk FOREIGN KEY (aid, bid) REFERENCES r
);
1 और 2 के दृष्टिकोण में अंतर यह है कि कोई गोलाकार FK नहीं हैं, इसलिए अपडेट और डिलीट करना ठीक रहेगा। "कुल भागीदारी" का प्रवर्तन अकेले डीडीएल द्वारा नहीं है, जैसा कि 2 के दृष्टिकोण में है, और उपयुक्त प्रक्रियाओं ( INSERT/UPDATE/DELETE/MERGE
) द्वारा किया जाना है । 2 के दृष्टिकोण के साथ एक मामूली अंतर यह है कि सभी स्तंभों को अशक्त नहीं परिभाषित किया जा सकता है।
एक और, 4 वीं दृष्टिकोण ( उपरोक्त प्रश्न में @Aaron बर्ट्रेंड का उत्तर देखें ) फ़िल्टर किए गए / आंशिक अद्वितीय अनुक्रमित का उपयोग करना है, यदि वे आपके DBMS में उपलब्ध हैं (आपको R
इस मामले के लिए तालिका में उनमें से दो की आवश्यकता होगी )। यह 3 जी दृष्टिकोण के समान है, सिवाय इसके कि आपको 2 अतिरिक्त तालिकाओं की आवश्यकता नहीं होगी। "कुल भागीदारी" बाधा अभी भी कोड द्वारा लागू की जानी है।