क्या डीबीएमएस हैं जो एक विदेशी कुंजी की अनुमति देते हैं जो एक दृश्य का संदर्भ देता है (और केवल बेस टेबल नहीं)?


22

एक Django मॉडलिंग प्रश्न से प्रेरित: Django में कई-से-कई संबंधों के साथ डेटाबेस मॉडलिंग । डीबी-डिज़ाइन कुछ इस तरह है:

CREATE TABLE Book
( BookID INT NOT NULL
, BookTitle VARCHAR(200) NOT NULL
, PRIMARY KEY (BookID)
) ;

CREATE TABLE Tag
( TagID INT NOT NULL
, TagName VARCHAR(50) NOT NULL
, PRIMARY KEY (TagID)
) ;

CREATE TABLE BookTag
( BookID INT NOT NULL
, TagID INT NOT NULL
, PRIMARY KEY (BookID, TagID)
, FOREIGN KEY (BookID)  REFERENCES Book (BookID)
, FOREIGN KEY (TagID)   REFERENCES Tag (TagID)
) ;

CREATE TABLE Aspect
( AspectID INT NOT NULL
, AspectName VARCHAR(50) NOT NULL
, PRIMARY KEY (AspectID)
) ;

CREATE TABLE TagAspect
( TagID INT NOT NULL
, AspectID INT NOT NULL
, PRIMARY KEY (TagID, AspectID) 
, FOREIGN KEY (TagID)   REFERENCES Tag (TagID)
, FOREIGN KEY (AspectID)  REFERENCES Aspect (AspectID)
) ;

db आरेख

और मुद्दा यह है कि BookAspectRatingतालिका को कैसे परिभाषित किया जाए और संदर्भात्मक अखंडता को लागू किया जाए, इसलिए कोई (Book, Aspect)संयोजन के लिए एक रेटिंग नहीं जोड़ सकता है जो अमान्य है।

AFAIK, जटिल CHECKअड़चनें (या ASSERTIONS) जिसमें उपश्रेणियाँ शामिल हैं और एक से अधिक तालिकाएँ, जो संभवतः इसे हल कर सकती हैं, किसी भी DBMS में उपलब्ध नहीं हैं।

एक अन्य विचार एक दृश्य का उपयोग करना है (छद्मकोड):

CREATE VIEW BookAspect_view
  AS
SELECT DISTINCT
    bt.BookId
  , ta.AspectId
FROM 
    BookTag AS bt
  JOIN 
    Tag AS t  ON t.TagID = bt.TagID
  JOIN 
    TagAspect AS ta  ON ta.TagID = bt.TagID 
WITH PRIMARY KEY (BookId, AspectId) ;

और एक तालिका जिसमें उपरोक्त दृश्य के लिए एक विदेशी कुंजी है:

CREATE TABLE BookAspectRating
( BookID INT NOT NULL
, AspectID INT NOT NULL
, PersonID INT NOT NULL
, Rating INT NOT NULL
, PRIMARY KEY (BookID, AspectID, PersonID)
, FOREIGN KEY (PersonID)   REFERENCES Person (PersonID)
, FOREIGN KEY (BookID, AspectID) 
    REFERENCES BookAspect_view (BookID, AspectID)
) ;

तीन प्रश्न:

  • क्या डीबीएमएस हैं जो एक (संभवतः भौतिक रूप से) VIEWएक के साथ अनुमति देते हैं PRIMARY KEY?

  • वहाँ डीबीएमएस है कि एक के लिए अनुमति देते हैं FOREIGN KEYकि REFERENCESएक VIEW(और न केवल एक आधार TABLE)?

  • क्या यह अखंडता समस्या हल हो सकती है - उपलब्ध डीबीएमएस सुविधाओं के साथ?


स्पष्टीकरण:

के बाद से वहाँ शायद कोई 100% संतोषजनक समाधान है - और Django सवाल भी मेरा नहीं है! - मैं समस्या पर संभावित हमले की एक सामान्य रणनीति में अधिक दिलचस्पी रखता हूं, विस्तृत समाधान नहीं। तो, "डीबीएमएस-एक्स में" जैसे उत्तर को तालिका ए पर ट्रिगर के साथ किया जा सकता है , पूरी तरह से स्वीकार्य है।


अपने पहले दो प्रश्नों के लिए एक टिप्पणी के रूप में पोस्टिंग - और जरूरी नहीं कि आपके लिए, क्योंकि मुझे यकीन है कि आप पहले से ही अवगत हैं - लेकिन SQL सर्वर विचारों के लिए प्राथमिक या विदेशी कुंजी का समर्थन नहीं करता है।
हारून बर्ट्रेंड

@ ऐरन: हाँ, धन्यवाद। मैंने पढ़ा है कि Oracle विचारों में PK लागतों का समर्थन करता है। लेकिन यकीन नहीं है कि यह इस स्थिति में काम करेगा। और 2 वें सवाल का जवाब (विचारों के बारे में FKs) शायद Oracle में नकारात्मक है।
ypercube y

लेकिन मुझे यह जानने में दिलचस्पी है कि क्या कोई अन्य समाधान (ट्रिगर, चेक कॉस्ट्रेन या अन्य कॉम्बो है)
ypercube12

जवाबों:


9

इस व्यापार नियम को केवल बाधाओं का उपयोग करके मॉडल में लागू किया जा सकता है। निम्न तालिका को आपकी समस्या का समाधान करना चाहिए। अपने दृष्टिकोण के बजाय इसका उपयोग करें:

    CREATE TABLE BookAspectCommonTagLink
    (  BookID INT NOT NULL
    , AspectID INT NOT NULL
    , TagID INT NOT NULL
--TagID is deliberately left out of PK
    , PRIMARY KEY (BookID, AspectID)
    , FOREIGN KEY (BookID, TagID) 
        REFERENCES BookTag (BookID, TagID)
    , FOREIGN KEY (AspectID, TagID) 
        REFERENCES AspectTag (AspectID, TagID)
    ) ;

ओह अच्छा। एकमात्र मुद्दा जो मुझे लगता है कि बुकटैग और टैगअस्पेक्ट्स को सम्मिलित / हटाने में शुरू की गई जटिलता है। हर बार एक नया बुकटैग (या टैगएस्पेक्ट) उदाहरण के लिए हटा दिया जाता है, इस तालिका में संबंधित पंक्तियों को हटाने और / या TagIDएक अन्य टैग में परिवर्तन करने के लिए एक खोज करनी पड़ती है जो उसी बुकएस्पेक्ट संयोजन से संबंधित है।
ypercube y

और इसी तरह की खोज उन 2 तालिकाओं में डालने के लिए की जाएगी। लेकिन जटिल नियमों के लिए जटिल प्रक्रियाओं की आवश्यकता होती है, इसलिए यह वास्तव में अच्छा लगता है।
ypercube y

@ypercube जब आप किसी टैग को हटाते हैं, तो आपको उसी बुक और एस्पेक्ट को लिंक करने वाले दूसरे टैग पर जांचने और संभवतः स्विच करने की आवश्यकता होती है। जब आप नए टैग सम्मिलित करते हैं, हालांकि, तब तक आपको कोई भी जांच करने की आवश्यकता नहीं होती है जब तक आपको रेटिंग डालने की आवश्यकता नहीं होती है।
एके

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

4
@AaronBertrand आपने बस मेरा बहुत बड़ा उपकार किया। मैं "विकासशील कम रखरखाव डेटाबेस" नामक एक लेख को समाप्त कर रहा हूं, और मैं यह उल्लेख करना भूल गया कि डेटाबेस से आने वाले मूल त्रुटि संदेशों को ऐप सर्वर को लॉग इन करना होगा। मैंने अभी इसे जोड़ा है। याद दिलाने के लिए धन्यवाद;)
AK

8

मुझे लगता है कि आप पाएंगे कि बहुत सारे मामलों में, जटिल व्यावसायिक नियमों को अकेले मॉडल के माध्यम से लागू नहीं किया जा सकता है। यह उन मामलों में से एक है, जहां कम से कम SQL सर्वर में, मुझे लगता है कि एक ट्रिगर (अधिमानतः एक ट्रिगर के बजाय) बेहतर आपके उद्देश्य को पूरा करता है।


हे हारून, क्या आप बता सकते हैं कि इस मामले में एक इकाई और कुछ बाधाओं की तुलना में ट्रिगर एक बेहतर विकल्प क्यों है?
एके

2
@AlexKuznetsov ज़रूर, क्योंकि मैंने यह सोचकर 17 घंटे नहीं बिताए कि इसे बहु-स्तंभ वाली विदेशी कुंजियों के साथ कैसे लागू किया जाए, और सभी अतिरिक्त तर्क जो कि वैसे भी सत्यापन और त्रुटि से निपटने के लिए आवश्यक हो सकते हैं?
हारून बर्ट्रेंड

2
ट्रिगर की भोली कार्यान्वयन शुरू हो सकता है कि दौड़ की स्थिति के बारे में सावधान रहें। उदाहरण के लिए, एक लेन-देन टैग से एक पुस्तक को डिस्कनेक्ट कर सकता है और दूसरा अभी भी सोचता है कि संबंधित पहलू से कनेक्ट करना ठीक है, सिर्फ इसलिए कि पहला लेनदेन अभी तक प्रतिबद्ध नहीं है। @AlexKuznetsov उत्तर द्वारा शुरू की गई जटिलताएं शायद ट्रिगर, IMHO में दौड़ की स्थिति को रोकने के लिए आवश्यक लॉकिंग "प्रोटोकॉल" की जटिलता और नाजुकता से कम हैं।
ब्रांको दिमित्रिजेविक

8

ओरेकल में, एक घोषणात्मक फैशन में इस तरह की बाधा को लागू करने का एक तरीका भौतिकवादी दृश्य बनाना होगा जो कि तेजी से ताज़ा करने के लिए तैयार है, जिसकी क्वेरी सभी अमान्य पंक्तियों (यानी उन BookAspectRatingपंक्तियों की पहचान करती है जिनका कोई मिलान नहीं है BookAspect_view)। फिर आप उस भौतिकवादी दृष्टिकोण पर एक तुच्छ बाधा पैदा कर सकते हैं जिसका उल्लंघन किया जाएगा यदि भौतिक दृष्टि से कोई पंक्तियाँ हैं। इससे भौतिक रूप में आपको डुप्लिकेट होने वाले डेटा की मात्रा को कम करने का लाभ होता है। हालाँकि, यह समस्या पैदा कर सकता है, क्योंकि बाधा केवल इस बिंदु पर लागू होती है कि आप लेन-देन कर रहे हैं- बहुत से आवेदन यह उम्मीद करने के लिए नहीं लिखे गए हैं कि एक प्रतिबद्ध ऑपरेशन विफल हो सकता है - और क्योंकि बाधा उल्लंघन कुछ हद तक कठिन हो सकता है किसी विशेष पंक्ति या किसी विशेष तालिका के साथ संबद्ध करना।


4

SIRA_PRISE इसकी अनुमति देता है।

हालांकि FK को अब "FK" नहीं कहा जाता है, लेकिन सिर्फ "डेटाबेस की कमी" है, और "दृश्य" वास्तव में एक दृश्य के रूप में परिभाषित करने के लिए भी नहीं है, आप बस घोषणा के अंदर दृश्य को परिभाषित करने वाली अभिव्यक्ति को शामिल कर सकते हैं। डेटाबेस की कमी।

आपकी अड़चन कुछ ऐसी दिखती होगी

SEMIMINUS(BOOKASPECT , JOIN(BOOKTAG , TAGASPECT))

और आपने कल लिया।

हालाँकि, अधिकांश SQL DBMS में आपको अपने अवरोध पर विश्लेषण कार्य करना होगा, यह निर्धारित करना होगा कि इसका उल्लंघन कैसे किया जा सकता है और सभी आवश्यक ट्रिगर को लागू किया जा सकता है।


मुझे पता है। यह दर्शाता है कि लेखन के समय मैंने जो सोचा था वह महत्वपूर्ण था।
एरविन स्मौट

3

PostgreSQL में, मैं ट्रिगर्स को शामिल किए बिना एक समाधान की कल्पना नहीं कर सकता, लेकिन यह निश्चित रूप से उस तरह से हल किया जा सकता है (जैसे कि यह किसी तरह का भौतिक दृष्टिकोण को बनाए रखता है या पहले ट्रिगर पर BookAspectRating)। कोई विदेशी कुंजी नहीं है जो एक दृश्य को संदर्भित करती है ( ERROR: referenced relation "v_munkalap" is not a table), अकेले एक प्राथमिक कुंजी दें।

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