2

(Apologies for any bad formatting or ignorance of common practices within this community; this is my first question here.)

I'm attempting to (re)design a MySQL database for a personal social networking site I'm developing. Quite often, I run into situations where there is an element (such as a "like" button) that requires a globally unique id despite being associated with a variety of different "parent" element types (blog post, comment, user page, etc). Previously, my design had been giving every like button a column for blog_id, comment_id, and user_id, and leaving the irrelevant columns NULL; if a like button is on a blog post with id 5, blog_id would be set to 5 while comment_id and user_id were NULL.

This implementation seemed redundant and unmaintainable, so I searched up alternative solutions.

The best solution I found seemed to be to define a new table, say like_buttons, with a primary key like_button_id that would be provided in a foreign key column within all other significant tables (blog_posts, comments, users). Then, whenever a like button's data must be accessed, one can search for the like_button_id column of the appropriate parent element, and go on from there.

However, when defining new comments and blog posts, I do not wish to have to add another line to my code separately defining a new like button just to pass the id to the significant element. Consequently, I stumbled upon MySQL's trigger functionality in searching for a solution.

To avoid further protracted exposition, my question lies in the acceptability of the following example code:

TRIGGER insert_user_like_button
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
  INSERT INTO like_buttons VALUES();
  SET NEW.like_button_id = LAST_INSERT_ID();
END

This trigger would be repeated for every other parent element table, such as blog_posts and comments.

Assuming that like_buttons (in this example case) only has one id NOT NULL PRIMARY KEY AUTO_INCREMENT column, is this the best method for preserving uniqueness in ids across multiple tables of information? Is there any more elegant, efficient, extendable, or appropriate solution?

1 Answer 1

1

I was going to write a long post telling you that there are basically 3 ways to implement polymorphic associations, but someone (@Bill Karwin) has already done it better in a more compact way: http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back/32

Your original solution is the first one presented on the slides, the one you propose is the 3rd one (but without using a base, parent table -more on this later), and maybe one can argue that is the one that seems the "cleanest". The actual preferred solution is not always the cleanest, but the best fit for the queries to be done. For example, the single table like_buttons may be much easier to query, but it can grow very tall. Having separate tables, like in solution #2 on the slides can be helpful as we are doing some kind of manual horizontal partitioning. On the other side, having separate tables may be less flexible, as it may force us to change the code if we add another entity part of the polymorphism. Also, there is a more direct relation in the direction like_button -> entity_to_be_liked.

Regarding specifically the trigger, I have nothing against the concept, but I am not sure if it is useful, as on creation time it is completely empty. Can't it be created on the first "like"? Referential integrity will already be secured if you create the extra generic table that I mentioned.

1
  • Thank you; this verified the validity of my approach. As far as triggers go, the existence of an id at creation time was not as much for the database's purposes as it was for web development simplicity. This is the DBA Stack Exchange, not Stack Overflow, so I won't go into too much detail. However, the website generates both a "like button" and a popup window to view who has liked any given post/page; if the like_button id was not generated until someone liked the post, then someone trying to examine an unliked post might get a "nonexistent object error" or something. That was my reasoning.
    – RNanoware
    Jul 23, 2014 at 19:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.