SQL में कुल भागीदारी बाधाओं के साथ कई-से-कई संबंधों का कार्यान्वयन


17

SQL में मुझे निम्नलिखित एंटिटी-रिलेशनशिप आरेख में दर्शाए गए परिदृश्य को कैसे लागू करना चाहिए?

कुल भागीदारी बाधाओं के साथ कई-से-कई संबंध

जैसा कि दिखाया गया है, प्रत्येक Aइकाई प्रकार की घटना कम से कम एक B समकक्ष (डबल कनेक्टिंग लाइनों द्वारा इंगित), और इसके विपरीत से संबंधित होनी चाहिए । मुझे पता है कि मुझे तीन तालिकाओं का पालन करना चाहिए:

    CREATE TABLE A
    (
        a INT NOT NULL,
        CONSTRAINT A_PK PRIMARY KEY (a)
    );

    CREATE TABLE B
    (
        b INT NOT NULL,
        CONSTRAINT B_PK PRIMARY KEY (b)
    );

    CREATE TABLE R
    (
        a INT NOT NULL,
        b INT NOT NULL,
        CONSTRAINT R_PK      PRIMARY KEY (a, b),
        CONSTRAINT R_to_A_FK FOREIGN KEY (a)
            REFERENCES A (a),
        CONSTRAINT R_to_B_FK FOREIGN KEY (b)
            REFERENCES B (b)
    );

लेकिन, कुल भागीदारी बाधाओं के कार्यान्वयन के बारे में क्या है (यानी, लागू करना कि या तो प्रत्येक का उदाहरण Aया दूसरे के साथ एक संबंध घटने Bमें शामिल है )?

जवाबों:


16

यह एसक्यूएल में करना आसान नहीं है लेकिन यह असंभव नहीं है। यदि आप अकेले 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)कॉलम को परिभाषित करना है NULLINSERTप्रक्रियाओं / बयान तो में पहले डालने करना होगा 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 अतिरिक्त तालिकाओं की आवश्यकता नहीं होगी। "कुल भागीदारी" बाधा अभी भी कोड द्वारा लागू की जानी है।


चौथा दृष्टिकोण (थोड़ा छिपा हुआ) वास्तव में परिपूर्ण है। एक उदाहरण के रूप में, पोस्टग्रेज के लिए postgresql.org/docs/9.6/static/indexes-partial.html उदाहरण 11-3 देखें ।
डैनिलो

@ डैनिलो मैं देखता हूं कि यह सुनिश्चित करना सही है कि अधिकतम 1 कुल भागीदारी है (कुछ अतिरिक्त क्षेत्र के आधार पर - पोस्टग्रे उदाहरण में सफलता)। मैं यह नहीं देख सकता कि यह सुनिश्चित करने में मदद कैसे हो कि कम से कम एक सफलता हो - इस धागे में वास्तविक प्रश्न। क्या आप कृपया विस्तार से बता सकते हैं?
अलेक्जेंडर मिहेलोव

3

आप सीधे नहीं कर सकते। शुरुआत के लिए, आप पहले से मौजूद बी के बिना ए के लिए रिकॉर्ड डालने में सक्षम नहीं होंगे, लेकिन यदि आप इसके लिए कोई रिकॉर्ड नहीं है तो आप बी रिकॉर्ड नहीं बना सकते हैं। ट्रिगर्स जैसी चीजों का उपयोग करके इसे लागू करने के कई तरीके हैं - आपको प्रत्येक प्रविष्टि पर जांचना होगा और हटाना होगा कि एबी लिंक तालिका में कम से कम एक संगत रिकॉर्ड रहता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.