मुझे यहाँ कुछ भी चक्रीय नहीं दिख रहा है। कर रहे हैं लोगों को और पदों और इन संस्थाओं के बीच दो स्वतंत्र रिश्ते। मैं इनमें से किसी एक रिश्ते के कार्यान्वयन के रूप में पसंद देखूंगा ।
- एक व्यक्ति कई पोस्ट लिख सकता है, एक पोस्ट एक व्यक्ति द्वारा लिखी जाती है:
1:n
- एक व्यक्ति कई पदों को पसंद कर सकता है, एक पोस्ट को कई लोगों द्वारा पसंद किया जा सकता है:
n:m
n: m संबंध किसी अन्य संबंध के साथ लागू किया जा सकता है likes
:।
मूल कार्यान्वयन
मूल कार्यान्वयन PostgreSQL में इस तरह दिख सकता है :
CREATE TABLE person (
person_id serial PRIMARY KEY
, person text NOT NULL
);
CREATE TABLE post (
post_id serial PRIMARY KEY
, author_id int NOT NULL -- cannot be anonymous
REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE -- 1:n relationship
, post text NOT NULL
);
CREATE TABLE likes ( -- n:m relationship
person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE
, post_id int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE
, PRIMARY KEY (post_id, person_id)
);
विशेष रूप से ध्यान दें कि एक पोस्ट में एक लेखक ( ) होना चाहिएNOT NULL
, जबकि पसंद का अस्तित्व वैकल्पिक है। मौजूदा पसंद के लिए, हालाँकि, post
और दोनों को संदर्भित किया person
जाना चाहिए (इसके द्वारा लागू किया गया PRIMARY KEY
है) दोनों कॉलम NOT NULL
स्वचालित रूप से बनाता है (आप इन बाधाओं को स्पष्ट रूप से जोड़ सकते हैं, अनावश्यक रूप से) इसलिए अनाम पसंद भी असंभव है।
एन के लिए विवरण: एम कार्यान्वयन:
आत्मचिंतन को रोकें
आपने भी लिखा:
(बनाया गया व्यक्ति अपने पद को पसंद नहीं कर सकता है)।
यह उपरोक्त कार्यान्वयन में लागू नहीं है, फिर भी। आप एक ट्रिगर का उपयोग कर सकते हैं ।
या इनमें से एक तेज / अधिक विश्वसनीय समाधान:
लागत के लिए रॉक-सॉलिड
यह होने की जरूरत है, तो रॉक-ठोस , आप से FK का विस्तार कर सकता likes
करने के लिए post
शामिल करने के लिए author_id
प्रचुरता से। फिर आप एक साधारण CHECK
बाधा के साथ अनाचार को नियंत्रित कर सकते हैं ।
CREATE TABLE likes (
person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE
, post_id int
, author_id int NOT NULL
, CONSTRAINT likes_pkey PRIMARY KEY (post_id, person_id)
, CONSTRAINT likes_post_fkey FOREIGN KEY (author_id, post_id)
REFERENCES post(author_id, post_id) ON UPDATE CASCADE ON DELETE CASCADE
, CONSTRAINT no_self_like CHECK (person_id <> author_id)
);
इसके लिए एक अन्यथा अतिरेक UNIQUE
अवरोध की भी आवश्यकता होती है post
:
ALTER TABLE post ADD CONSTRAINT post_for_fk_uni UNIQUE (author_id, post_id);
मैंने author_id
सबसे पहले एक उपयोगी इंडेक्स की आपूर्ति की, जबकि उस पर रहा।
अधिक के साथ संबंधित जवाब:
एक CHECK
बाधा के साथ सस्ता
ऊपर "मूल कार्यान्वयन" पर निर्माण।
CHECK
बाधाओं को अपरिवर्तनीय माना जाता है। एक जांच के लिए अन्य तालिकाओं को संदर्भित करना कभी भी अपरिवर्तनीय नहीं है, हम यहां अवधारणा का थोड़ा दुरुपयोग कर रहे हैं। मैं NOT VALID
ठीक से प्रतिबिंबित करने के लिए बाधा घोषित करने का सुझाव देता हूं । विवरण:
CHECK
इस विशेष मामले में एक बाधा उचित लगती है, क्योंकि एक पोस्ट के लेखक एक विशेषता की तरह लगता है जो कभी नहीं बदलता है। सुनिश्चित करने के लिए उस फ़ील्ड के अपडेट को अस्वीकृत करें।
हम एक समारोह नकलीIMMUTABLE
:
CREATE OR REPLACE FUNCTION f_author_id_of_post(_post_id int)
RETURNS int AS
'SELECT p.author_id FROM public.post p WHERE p.post_id = $1'
LANGUAGE sql IMMUTABLE;
अपनी तालिकाओं के वास्तविक स्कीमा से 'जनता' को बदलें।
एक CHECK
बाधा में इस समारोह का उपयोग करें :
ALTER TABLE likes ADD CONSTRAINT no_self_like_chk
CHECK (f_author_id_of_post(post_id) <> person_id) NOT VALID;