Tôi không thấy bất cứ điều gì đang tuần hoàn ở đây. Có những người và bài viết và hai mối quan hệ độc lập giữa các thực thể này. Tôi sẽ thấy thích là việc thực hiện một trong những mối quan hệ này.
- Một người có thể viết nhiều bài, một bài được viết bởi một người:
1:n
- Một người có thể thích nhiều bài đăng, một bài đăng có thể được nhiều người thích
n:m
: Mối quan hệ n: m có thể được thực hiện với một mối quan hệ khác : likes
.
Thực hiện cơ bản
Việc triển khai cơ bản có thể trông như thế này trong 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)
);
Đặc biệt lưu ý rằng một bài đăng phải có tác giả ( NOT NULL
), trong khi sự tồn tại của lượt thích là tùy chọn. Tuy nhiên, đối với các lượt thích hiện tại post
và cả hai person
phải được tham chiếu (được thực thi bởi PRIMARY KEY
điều đó làm cho cả hai cột NOT NULL
tự động (bạn có thể thêm các ràng buộc này một cách rõ ràng, dự phòng), vì vậy, các lượt thích ẩn danh cũng không thể.
Chi tiết cho việc thực hiện n: m:
Ngăn chặn tự thích
Bạn cũng đã viết:
(người được tạo ra không thể thích bài viết của mình).
Điều đó không được thi hành trong việc thực hiện ở trên. Bạn có thể sử dụng một kích hoạt .
Hoặc một trong những giải pháp nhanh hơn / đáng tin cậy hơn:
Rock-solid cho một chi phí
Nếu nó cần phải được đá rắn , bạn có thể kéo dài tuổi FK từ likes
để post
bao gồm các author_id
dư thừa. Sau đó, bạn có thể loại trừ loạn luân với một CHECK
ràng buộc đơn giản .
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)
);
Điều này đòi hỏi một UNIQUE
ràng buộc dư thừa khác trong post
:
ALTER TABLE post ADD CONSTRAINT post_for_fk_uni UNIQUE (author_id, post_id);
Tôi đặt author_id
đầu tiên để cung cấp một chỉ số hữu ích trong khi ở đó.
Câu trả lời liên quan với nhiều hơn:
Rẻ hơn với một CHECK
ràng buộc
Xây dựng trên "Thực hiện cơ bản" ở trên.
CHECK
các ràng buộc có nghĩa là bất biến. Tham khảo các bảng khác để kiểm tra là không bao giờ bất biến, chúng tôi đang lạm dụng khái niệm một chút ở đây. Tôi đề nghị khai báo các ràng buộc NOT VALID
để phản ánh đúng điều đó. Chi tiết:
Một CHECK
ràng buộc có vẻ hợp lý trong trường hợp cụ thể này, bởi vì tác giả của một bài đăng dường như là một thuộc tính không bao giờ thay đổi. Không cho phép cập nhật vào lĩnh vực đó để chắc chắn.
Chúng tôi giả mạo một IMMUTABLE
chức năng:
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;
Thay thế 'công khai' bằng lược đồ thực tế của các bảng của bạn.
Sử dụng chức năng này trong một CHECK
ràng buộc:
ALTER TABLE likes ADD CONSTRAINT no_self_like_chk
CHECK (f_author_id_of_post(post_id) <> person_id) NOT VALID;