Làm thế nào để tránh sự phụ thuộc theo chu kỳ (tham chiếu vòng tròn) giữa 3 bảng?


10

Tôi có 3 bảng:

  • Mọi người
  • Bài đăng
  • Thích

Khi tôi thiết kế mô hình ER, nó có một phụ thuộc theo chu kỳ:

         1: N
Mọi người -------- <Đăng

         1: N
Bài viết ---------- <Lượt thích

         1: N
Mọi người -------- <Thích

Logic là:

  • 1 người có thể có nhiều bài viết.

  • 1 bài đăng có nhiều lượt thích.

  • 1 người có thể thích nhiều bài đăng (người được tạo không thể thích bài đăng của mình).

Làm thế nào tôi có thể loại bỏ loại thiết kế tuần hoàn này? Hoặc là thiết kế db của tôi sai?

Câu trả lời:


10

Quy tắc kinh doanh

Hãy để chúng tôi thực hiện một số điều chỉnh lại các quy tắc kinh doanh mà bạn đã trình bày:

  • A Persontạo ra không-một-nhiều-nhiều Posts .
  • A Postnhận được không-một-nhiều-nhiều Likes .
  • Một Personbiểu hiện không có một hoặc nhiều Likes , mỗi câu liên quan đến một cụ thể Post .

Mô hình logic

Sau đó, từ tập hợp các xác nhận như vậy, tôi đã nhận được hai mô hình dữ liệu mức logic IDEF1X [1] được hiển thị trong Hình 1 .

Hình 1 - Mô hình dữ liệu về người và bài

Lựa chọn A

Như bạn có thể nhìn thấy trong Một mô hình lựa chọn, PersonId di chuyển [2] từ Personđến Postnhư một KEY NƯỚC NGOÀI (FK), nhưng nó nhận được tên vai trò [3] của AuthorId, và thuộc tính này chiếm, cùng với PostNumber, các PRIMARY KEY (PK) của Postloại thực thể.

Tôi giả định rằng một Likechỉ có thể tồn tại trong mối liên hệ với một đặc biệt Post, vì vậy tôi đã thiết lập một LikePK đó bao gồm ba thuộc tính khác nhau: PostAuthorId, PostNumberLikerId. Sự kết hợp của PostAuthorIdPostNumberlà một FK làm cho tham chiếu thích hợp đến PostPK. LikerIdđến lượt nó, một FK thiết lập mối liên kết phù hợp với Person.PersonId.

Với sự trợ giúp của cấu trúc này, bạn đảm bảo rằng một người xác định chỉ có thể biểu hiện một lần Likexuất hiện trong cùng một Posttrường hợp.

Các phương pháp để ngăn chặn một Tác giả bài viết thích bài viết của mình

Vì bạn không muốn cho phép khả năng một người có thể thích bài đăng của tác giả của mình, nên trong giai đoạn thực hiện, bạn nên thiết lập một phương pháp so sánh giá trị Like.PostAuthorIdvới giá trị Like.LikerIdtrong mỗi lần thử INSERT. Nếu các giá trị nói khớp với nhau, (a) bạn từ chối chèn, nếu chúng không khớp (b), bạn hãy để quá trình tiếp tục.

Để hoàn thành nhiệm vụ này trong cơ sở dữ liệu của bạn, bạn có thể sử dụng:

  1. Một hạn chế kiểm tra nhưng, dĩ nhiên, phương pháp này không bao gồm MySQL, vì nó đã không được thực hiện trong nền tảng này cho đến nay, như bạn thấy ở đâyở đây .

  2. Các dòng mã bên trong Giao dịch ACID .

  3. Các dòng mã trong TRIGGER , có thể trả về một thông báo tùy chỉnh cho biết nỗ lực vi phạm quy tắc.

Lựa chọn B

Nếu tác giả không phải là một thuộc tính xác định theo cách chính một bài đăng trong miền doanh nghiệp của bạn, bạn có thể đi với cấu trúc tương tự như cấu trúc được mô tả trong Tùy chọn B.

Cách tiếp cận này cũng đảm bảo rằng một bài viết chỉ có thể được yêu thích bởi cùng một người một lần duy nhất.


Ghi chú

1. Định nghĩa tích hợp cho mô hình hóa thông tin ( IDEF1X ) là một kỹ thuật mô hình hóa dữ liệu rất được khuyến khích , được định nghĩa là một tiêu chuẩn vào tháng 12 năm 1993 bởi Viện Tiêu chuẩn và Công nghệ Quốc gia Hoa Kỳ ( NIST ).

2. IDEF1X định nghĩa di chuyển khóa là một quy trình mô hình hóa việc đặt khóa chính của cha mẹ hoặc thực thể chung trong thực thể con hoặc thực thể của nó là một khóa ngoại khóa.

3. Tên vai trò là một ký hiệu được gán cho thuộc tính khóa ngoài để thể hiện ý nghĩa của thuộc tính đó trong ngữ cảnh của loại thực thể tương ứng. Việc đặt tên vai trò được đề xuất từ ​​năm 1970 bởi Tiến sĩ EF Codd trong bài báo chuyên đề của ông có tên là Mô hình dữ liệu quan hệ cho các ngân hàng dữ liệu chia sẻ lớn . Về phần mình, tính trung thực của IDEF1X về việc giữ liên quan đến các hoạt động quan hệ mà Google cũng ủng hộ thủ tục này.


6

Tôi không thấy bất cứ điều gì đang tuần hoàn ở đây. Có những ngườibà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 postvà 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 NULLtự độ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để postbao gồm các author_iddư thừa. Sau đó, bạn có thể loại trừ loạn luân với một CHECKrà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 UNIQUErà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 CHECKràng buộc

Xây dựng trên "Thực hiện cơ bản" ở trên.

CHECKcá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 CHECKrà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 IMMUTABLEchứ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 CHECKràng buộc:

ALTER TABLE likes ADD CONSTRAINT no_self_like_chk
   CHECK (f_author_id_of_post(post_id) <> person_id) NOT VALID;

4

Tôi nghĩ rằng bạn đang gặp khó khăn khi tìm hiểu điều này vì cách bạn nêu quy tắc kinh doanh của mình.

Người và bài viết là "đối tượng". Like là một động từ.

Bạn thực sự chỉ có 2 hành động:

  1. Một người có thể tạo một hoặc nhiều bài viết
  2. Nhiều người có thể thích nhiều bài viết. (tổng hợp 2 báo cáo cuối cùng của bạn)

mọi người thích sơ đồ bài viết

Bảng "thích" sẽ có person_id và post_id làm khóa chính.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.