एक ही तालिका में दो पंक्तियों को कैसे संबंधित करें


11

मेरे पास एक तालिका है जहाँ पंक्तियाँ एक-दूसरे से संबंधित हो सकती हैं, और तार्किक रूप से, दोनों पंक्तियों के बीच संबंध दोनों तरीके से (मूल रूप से, दिशाहीन है) जाता है। (और अगर आप सोच रहे हैं, हां, यह वास्तव में एक तालिका होनी चाहिए। यह एक ही तार्किक इकाई / प्रकार की दो चीजें हैं।) मैं इसे दर्शाने के लिए कुछ तरीके सोच सकता हूं:

  1. रिश्ते और उसके रिवर्स स्टोर करें
  2. रिश्ते को एक तरह से स्टोर करें, डेटाबेस को दूसरे तरीके से स्टोर करने से रोकें, और FKs के लिए विपरीत ऑर्डर के साथ दो इंडेक्स हों (एक इंडेक्स PK इंडेक्स हो)
  3. रिश्ते को दो अनुक्रमों के साथ एक तरह से स्टोर करें और दूसरे को वैसे भी डालने की अनुमति दें (ध्वनियों की तरह, लेकिन हे, पूर्णता)
  4. किसी प्रकार की समूहीकरण तालिका बनाएँ और उसमें मूल तालिका पर एक FK रखें। (बहुत से प्रश्न उठाता है। समूह तालिका में केवल एक संख्या होती है; तालिका भी क्यों होती है? FK को पूर्ण बनाएं या एकल पंक्ति से जुड़े समूह हैं?)

इन तरीकों के कुछ प्रमुख पेशेवरों और विपक्ष हैं, और निश्चित रूप से, क्या कोई ऐसा तरीका है जिसके बारे में मैंने नहीं सोचा है?

यहाँ एक SQLFiddle के साथ खेलने के लिए है: http://sqlfiddle.com/# -12/7ee1a /1/0 । (पोस्टग्रेएसक्यूएल होने के बाद से यह वही है जो मैं उपयोग कर रहा हूं, लेकिन मुझे नहीं लगता कि यह प्रश्न पोस्टग्रेक्यूएल के लिए बहुत विशिष्ट है।) यह वर्तमान में एक उदाहरण के रूप में रिश्ते और इसके रिवर्स दोनों को संग्रहीत करता है।


क्या एक दिया गया मूल्य एक से अधिक अन्य से संबंधित हो सकता है? क्या एक दिया गया मूल्य हमेशा दूसरे से संबंधित होता है? क्या वे समान डेटा साझा करते हैं?
फिलु

हां, वे 1 से अधिक अन्य पंक्ति से संबंधित हो सकते हैं। नहीं, वे जरूरी नहीं कि हमेशा दूसरी पंक्ति से संबंधित हों। जरूरी नहीं कि उनके पास कोई आम डेटा हो। धन्यवाद।
jpmc26

उफ़। @Phil को भूल गए। एक संभावित संरचना को जोड़ने के लिए भी संपादित किया गया जो अभी मेरे पास आई है।
jpmc26

जवाबों:


9

आपने जो डिजाइन किया है वह अच्छा है। जोड़े जाने की जरूरत है जो रिश्ते को दिशाहीन बनाने के लिए एक बाधा है। तो, आपके पास एक (1,5)पंक्ति नहीं हो सकती है और साथ ही एक पंक्ति भी नहीं (5,1)जोड़ी जा रही है।

यह पूरा किया जा सकता है * पुल की मेज पर एक आत्म संदर्भित बाधा के साथ।

* - यह Postgres, Oracle, DB2 और सभी DBMS में पूरा किया जा सकता है जो कि SQL मानक वर्णन (स्थगित, जैसे लेन-देन के अंत में जाँच की गई) के रूप में विदेशी प्रमुख बाधाओं को लागू किया है। Deferred जाँच की वास्तव में वैसे भी ज़रूरत नहीं है, जैसे SQL- में। सर्वर जो उन्हें बयान के अंत में जांचता है और यह निर्माण अभी भी काम करता है। आप MySQL में ऐसा नहीं कर सकते क्योंकि "InnoDB UNIQUE और FOREIGN KEY की कमी को पंक्ति-दर-पंक्ति जाँचता है"

तो, पोस्टग्रैज में निम्नलिखित आपकी आवश्यकताओं से मेल खाएगा:

CREATE TABLE x
(
  x_id SERIAL NOT NULL PRIMARY KEY,
  data VARCHAR(10) NOT NULL
);

CREATE TABLE bridge_x
(
  x_id1 INTEGER NOT NULL REFERENCES x (x_id),
  x_id2 INTEGER NOT NULL REFERENCES x (x_id),
  PRIMARY KEY(x_id1, x_id2),
  CONSTRAINT x_x_directionless
    FOREIGN KEY (x_id2, x_id1)
    REFERENCES bridge_x (x_id1, x_id2)
);

परीक्षण किया गया: एसक्यूएल-फिडल

यदि आप एक पंक्ति जोड़ने का प्रयास करते हैं (1,5):

INSERT INTO bridge_x VALUES
(1,5) ;

यह विफल रहता है:

त्रुटि: टेबल पर डालें या अपडेट करें "ब्रिज_एक्स" विदेशी कुंजी बाधा का उल्लंघन करता है "x_x_directionless"
विवरण: कुंजी (x_id2, x_id1) = (5, 1) तालिका "ब्रिज_x" में मौजूद नहीं है।:
INSERT INTO Bridge_x VALUES (1,5)

CHECKयदि आप (y,y)पंक्तियों को करना चाहते हैं, तो इसके अतिरिक्त, आप एक बाधा जोड़ सकते हैं :

ALTER TABLE bridge_x
  ADD CONSTRAINT x_x_self_referencing_items_not_allowed
    CHECK (x_id1 <> x_id2) ;

इसे लागू करने के अन्य तरीके हैं, जैसा कि आप उल्लेख करते हैं, जैसे कि रिश्ते की केवल एक दिशा (एक पंक्ति में, दो नहीं) को स्टोर करने के लिए निम्न आईडी x_id1और x_id2कॉलम में उच्च आईडी को मजबूर करके । इसे लागू करना आसान लगता है, लेकिन आमतौर पर बाद में अधिक जटिल प्रश्नों की ओर जाता है:

CREATE TABLE bridge_x
(
  x_id1 INTEGER NOT NULL REFERENCES x (x_id),
  x_id2 INTEGER NOT NULL REFERENCES x (x_id),
  PRIMARY KEY(x_id1, x_id2),
  CONSTRAINT x_x_directionless
    CHECK (x_id1 <= x_id2)                       -- or "<" to forbid `(y,y)` rows
);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.