I have a structure for a notification system that I believe is pretty dynamic, though I fear my solution may be breaking some sort of cardinal rule of database design.
Notifications
id
notification_type_id
data
created_at
Users Notifications
user_id
notification_id
is_read
The part that I question is the data column in the notifications table, which is to hold the relevant data (in json format) necessary to build the message. For instance, if the notification is for a new comment added on a post, then data would contain the id of the post as well as the id of the user who commented on the post to build the necessary message.
Example: {post_id: 123, user_id: 456} would build the message “Dumbo answered your question How much does it cost to…?”
The thought of having one column hold multiple references to other records hits me wrong, but it does seem like a pretty dynamic option. If not this, the only other option I can think of is to generate the message prior and then storing that in the database, which seems too static to me as everybody involved would receive the same exact message.
The relational model allows arbitrarily complex types. But if a complex type has some internal structure, then
Dates, for example, have internal structure. Database management systems provide functions to manipulate that structure by truncating it, extracting parts of it, adding and subtracting intervals, and so on.
JSON has internal structure, too. If your DBMS supports a JSON data type, it will provide functions to manipulate it. If it doesn’t, it ignores the fact that it’s a JSON type, and just returns the stored JSON data to the user.
So far, no problem.
But, having said that . . .
One problem here is that the dbms can’t guarantee that user_id 456 exists, so the caller can’t know whether the conversion from ID number to name will work. It also can’t know whether post ID 123 still exists. Those kinds of constraints are what foreign keys are for, and you can’t enforce foreign key constraints on id numbers stored as JSON.
Your main risk there is returning nonsense (or NULL) to the caller. In some cases, that’s perfectly defensible. (Blogs, for example. Who really cares if you get a nonsense message once in a while?) In other cases, it might be catastrophic.
If, instead, you stored the text “Dumbo answered your question, ‘How much …'”, there would be no chance of failure because of deleted users or posts. Even if both the post and user were deleted, the message “Dumbo answered your question, ‘How much …'” would still be a true fact. (Though perhaps somewhat less useful, depending on how your system handles deletions.)