Another approach to this would be to never edit or delete your data, but create new data. In SQL terms, the only operations you perform in your tables are INSERT and SELECT.
To accomplish what you want, the following columns are needed for each table:
- version_id - this will be your main key.
- id - this will be what supports the versions of your object together (for example, to find all product versions, SELECT * FROM products WHERE id =?)
- CREATION_DATE
- is_active - you do not delete anything, so you need to mark (logically) get rid of the data
With this, here is what your product table looks like:
CREATE TABLE products ( version_id CHAR(8) NOT NULL PRIMARY KEY, id INTEGER NOT NULL, creation_date TIMESTAMP NOT NULL DEFAULT NOW(), is_active BOOLEAN DEFAULT true, name VARCHAR(1024) NOT NULL, price INTEGER NOT NULL ); CREATE TABLE variants ( version_id CHAR(8) NOT NULL PRIMARY KEY, id INTEGER NOT NULL, creation_date TIMESTAMP NOT NULL DEFAULT NOW(), is_active BOOLEAN DEFAULT true, product_version_id CHAR(8) NOT NULL, price INTEGER NOT NULL, override_price INTEGER NOT NULL, FOREIGN KEY (product_version_id) REFERENCES products(version_id) );
Now to insert into both tables
- Create a unique version of id (there are several strategies for this: you need to use a database sequence or use MySQL ant AUTO_INCREMENT).
- Generate an identifier. This identifier is consistent for all versions of the product.
To update a row in a table, you need to insert the entire graph, for example. To update a product, you need to insert a new product and new options. (There are many opportunities for optimization, but the easiest way to start is with an unoptimized solution.)
For example, to update a product
- Create a unique version_id file
- Use the same identifier
- Insert new product options. The options will be the same as those associated with the previous version of the product you are updating, except that product_version_id will be different.
This principle can apply to all your tables.
To find the latest version of a product, you need to use the create_date column to get the product that was recently created.
This model will use more space, but I think it can be a fair compromise, given its simplicity: there is only INSERT and SELECT, and the data is never mutated.