ฉันไม่เห็นอะไรเลยที่เป็นวัฏจักรที่นี่ มีบุคคลและโพสต์และสองความสัมพันธ์อิสระระหว่างหน่วยงานเหล่านี้ ฉันเห็นว่าการถูกใจใช้งานความสัมพันธ์เหล่านี้อย่างใดอย่างหนึ่ง
- บุคคลสามารถเขียนบทความได้หลายโพสต์เขียนโดยคนคนเดียว:
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
โดยอัตโนมัติ (คุณอาจเพิ่มข้อ จำกัด เหล่านี้อย่างชัดเจนซ้ำซ้อน) เพื่อให้ไลค์ที่ไม่ระบุชื่อเป็นไปไม่ได้
รายละเอียดสำหรับการใช้งาน n: m:
ป้องกันตนเองเหมือน
คุณยังเขียนว่า:
(คนที่สร้างขึ้นไม่สามารถชอบโพสต์ของเขาเอง)
ยังไม่ได้บังคับใช้ในการนำไปใช้ข้างต้น คุณสามารถใช้ทริกเกอร์
หรือหนึ่งในโซลูชันที่เร็วขึ้น / น่าเชื่อถือมากขึ้นเหล่านี้:
หินแข็งสำหรับค่าใช้จ่าย
หากจะต้องมีหินแข็งคุณสามารถขยาย 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;