I have 3 tables:
- People
- Post
- Likes
When I design the ER model it has a cyclic dependency:
1:N People --------< Post 1:N Post ----------< Likes 1:N People --------< Likes
The logic is:
-
1 people can have many posts.
-
1 post has many likes.
-
1 people can like many posts (created person cannot like his own post).
How can I remove this kind of cyclic design? Or is my db design wrong?
Best Answer
Business rules
Let us make some rewordings to the business rules you have presented:
Person
creates zero-one-or-manyPosts
.Post
receives zero-one-or-manyLikes
.Person
manifests zero-one-or-manyLikes
, each of wich pertains to one specificPost
.Logical models
Then, from such set of assertions, I have derived the two logical level IDEF1X[1] data models that are shown in Figure 1.
Option A
As you can see in the Option A model,
PersonId
migrates[2] fromPerson
toPost
as a FOREIGN KEY (FK), but it receives the role name[3] ofAuthorId
, and this attribute makes up, together withPostNumber
, the PRIMARY KEY (PK) of the thePost
entity type.I assume that a
Like
can only exist in connection with a particularPost
, so I have set up aLike
PK that comprises of three different attributes:PostAuthorId
,PostNumber
andLikerId
. The combination ofPostAuthorId
andPostNumber
is a FK that makes the proper reference to thePost
PK.LikerId
is, in turn, a FK that establishes the suitable association withPerson.PersonId
.With the aid of this structure, you ensure that a determined person can only manifest a single
Like
occurrence to the samePost
instance.Methods to prevent a Post Author from liking his own Post
Since you do not want to allow the possibility that a person can like his/her authored posts, once in the implementation phase, you should establish a method that compares the value of
Like.PostAuthorId
with the value ofLike.LikerId
in every INSERT attempt. If said values match, (a) you reject the insertion, if they do not match (b) you let the process continue.In order to accomplish this task in your database, you can make use of:
A CHECK CONSTRAINT but, of course, this method excludes MySQL, since it has not been implemented in this platform so far, as you can see here and here.
Code lines inside an ACID Transaction.
Code lines within a TRIGGER, which could return a custom message indicating the rule violation attempt.
Option B
If the author is not an attribute that identifies in a primary way a post in your business domain, you could go with a structure similar to the one depicted in Option B.
This approach also makes sure that a post can only be liked by the same person one single time.
Notes
1. Integration Definition for Information Modeling (IDEF1X) is a highly recommendable data modeling technique that was defined as a standard in december 1993 by the United States National Institute of Standards and Technology (NIST).
2. IDEF1X defines key migration as “The modeling process of placing the primary key of a parent or generic entity in its child or category entity as a foreign key”.
3. A role name is a denotation assigned to a foreign key attribute in order to express the meaning of such attribute in the context of its corresponding entity type. Role naming is recommended since 1970 by Dr. E. F. Codd in his seminal paper entitled “A Relational Model of Data for Large Shared Data Banks”. For its part, IDEF1X —keeping fidelity regards relational practices— also advocates this procedure.