According to Five Simple Database Design Errors You Should Avoid by Anith Sen, using a common-lookup table to store the possible statuses for an entity is a common mistake.
Edit + Answer: The figures in Anith’s article aren’t well labelled – I thought both Figure 1 and Figure 2 are examples of bad design, whereas Figure 2 is good design. Phew, got worried there for a moment.
In summary:
- Lookup tables: good.
- Common-lookup tables: bad.
I’ll keep my question below for reference.
The following reasons are given:
“You lose the means to ensure accurate
data; constraints. By combining
different entities into a single
table, you have no declarative means
to restrain values of a certain
category.”
How is constraining values losing accuracy?“You are forced to represent
every data type as a string with this
type of generic lookup table.”
If I want to represent another data type, I can add a column for it to my lookup table.“You commit yourself to
rigidity and subsequent complexity.”
How?Fourthly and finally, you are faced
with the physical implementation
issues.
I don’t see why.
I disagree with most of the reasons given and would like some objective critique on my incorrect? logic.
My examples:
Citing the example of jobs at a repair service with many possible statuses that generally have a natural flow, let’s take a JobStatus table:
- Booked In
- Assigned to Technician
- Diagnosing problem
- Waiting for Client Confirmation
- Repaired & Ready for Pickup
- Repaired & Couriered
- Irreparable & Ready for Pickup
- Quote Rejected
Arguably, some of these statuses can be normalised to tables like Couriered Items, Completed Jobs and Quotes (with Pending/Accepted/Rejected statuses), but that feels like unnecessary schema complication.
Another common example would be an OrderStatus table to restrict the status of an order:
- Pending
- Completed
- Shipped
- Cancelled
- Refunded
The status titles and descriptions are in one place for editing and are easy to scaffold as a drop-down with a foreign key for dynamic data applications. This has worked well for me in the past. If the business rules dictate the creation of a new order status, I can just add it to OrderStatus table, without rebuilding my code.
Why is this a bad practice?
Edits: I added Anith’s reason to my question and tried to remain objective.
—
What Anith Sen is advising against is having a single lookup table for all lookup codes. That is the significance of the
categorycolumn in his example. Having a separate table for each category is definitely the way to go.This is because:
In your examples JobStatus and OrderStatus are separate categories. applicable to separate entities. That is why they need different look-up tables. There is not even a problem with sharing the same code table across several different data tables. Where it becomes problematic is when we have separate data tables (entities) for which some statuses are not appropriate: that is the time to split the codes out into separate look-up tables.
edit
I see you have edited your post to cite all of Anith’s points. I think the most important point one is the first one, regarding constraints. If you want to restrict the ORDERS.STATUS column to have values from the OrderStatus category then you have to have a separate table to enforce a foreign key. Your alternatives are:
All of those options suck, from the database perspective.