This is interesting because I've never heard of the term OTLT and I also think it's a bad idea but I can see myself having implemented somthing like this in one of my databases. The reason was I couldn't think of any better way. The scenario is: I want to track all changes that admin users make to orders. The obvious design choice came to my mind - have a log table where each row has information about a single change a user made at a certain point in time. But the problem is there are many different types of changes a user can make:
- change data of a field - there any many fields like name, surname, street, status, etc. where each can have a different lenght and can also be of a different type
- change a boolean property (checkboxes) of a field
- add a product
- remove a product
- change price of a product
- change quantity of a product
- etc...
How do I store in a single row data of such big variety? What I ultimatelty wanted to do is simply display the list of changes with their descriptions under a given order sorted by date and time - in a readable table. I thought that creating a separate table for each type of change will be a nightmare because I will end up with more than 10 separate tables just for the sake of this changelog. So I decided to use just one table with all fields I might need, general TEXT column to contain any type of data and of course most of the columns end up being NULL. Then my application interprets the data and changes into human readable descriptions.
This is the table (simplified for the sake of this discussion):
Code:
CREATE TABLE `order_change` (
`change_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`order_id` MEDIUMINT(8) UNSIGNED NOT NULL,
`change_time` DATETIME NOT NULL,
`change_type` CHAR(2) NOT NULL,
`field` VARCHAR(25) NULL DEFAULT NULL,
`old_value` TEXT NULL,
`new_value` TEXT NULL,
`product_position` SMALLINT(5) UNSIGNED NULL DEFAULT NULL COMMENT 'position of product in order',
`prod_id` MEDIUMINT(8) UNSIGNED NULL DEFAULT NULL,
`product_name` VARCHAR(255) NULL DEFAULT NULL,
`vat` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
`qty` SMALLINT(5) UNSIGNED NULL DEFAULT NULL,
`price` DECIMAL(9,2) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`change_id`),
INDEX `FK2_order_id` (`order_id`),
CONSTRAINT `FK2_order_id` FOREIGN KEY (`order_id`) REFERENCES `shop_order` (`order_id`) ON UPDATE CASCADE ON DELETE CASCADE
)
ENGINE=InnoDB;
I know it's a bit ugly, one table holds all types of data. I still can't think of a better way, does anyone have any ideas? The question is theoretical because the system I made works very well but I'm left with a feeling this design is a bit ugly.
Bookmarks