Basic mysql versioning? Basic mysql versioning? database database

Basic mysql versioning?


You can do what ERP (and also possibly Payroll) systems do: Add a Start and End Date/Time. So...

  • the variant and prices match with their product based on the common dates.
  • all queries default to running on current date and the joins between each table need to also take into account the overlapping/intersecting date ranges. parent_start_date <= child_start_date AND parent_end_date >= child_end_date
  • You would end up with duplicated rows for each price change or variant but you then don't need to keep update as many records (like variant ids) when the product price changes.
  • Need to ensure valid dates are used. PS: Use your system's max date for the End datetime of the most current/recent record.

Btw, some related questions along the same line:


Another approach to this would be to never edit or remove your data, only create new data. In SQL terms, the only operations you ever run on your tables are INSERTs and SELECTs.

To accomplish what you want, each table would need the following colums:

  • version_id - this would be your primary key
  • id - this would be the thing that holds versions of your object together (e.g. to find all versions of a product, SELECT * FROM products WHERE id = ?)
  • creation_date
  • is_active - you're not deleting anything, so you need to flag to (logically) get rid of data

With this, here's what your products table would look 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 either table

  1. Generate a unique version_id (there are several strategies for this, one is to use a database sequence, or for MySQL use ant AUTO_INCREMENT).
  2. Generate an id. This id is consistent for all versions of a product.

To update a row in a table, one must insert the entire graph e.g. to update a product, one must insert a new product, and new variants. (There is a lot of room for optimization here, but it's easiest to start with the un-optimized solution.)

For example, to update a product

  1. Generate a unique version_id
  2. Use the same id
  3. Insert new product variants. The variants will be the same as the ones linked to the previous version of the product that you're "updating", except the product_version_id will be different.

This principal can extend to all your tables.

To find the most recent version of a product, you need to use the creation_date column to get the product that was most recently created.

This model will use more space, but I think this may be a fair trade-off given it's simplicity: there are only INSERTs and SELECTs and data is never mutated.