0

My database requires some columns to be tracked, but not all. I've looked at a couple of designs to implement tracking such as(Ideas on database design for capturing audit trails).

However this seems highly wasteful and since I only really need to track a couple of critical columns I feel like this wouldn't be the optimal solution for me.

Now I thought of a way to tackle my situation, but I am not sure if I might be overlooking a design flaw with this approach.

User
----
ID PK        INT
Username     VARCHAR(MAX)    

Employee
-----
ID PK        INT
Name         VARCHAR(MAX)

PensionScheme
-------------
ID PK         INT
EmpID FK      INT (References Employee)
IsActive      BOOLEAN
ModifiedBy FK INT (References User)
EffectiveFrom DATETIME

The schema above is just a highly simplified example, but captures the essence.

Essentially an Employee can be on a pension scheme or not, the changes to this attribute have to tracked. When a change to that attribute needs to happen a new row is inserted with a timestamp.

If you want to figure out whether the employee is on a pension scheme or not you would have to find the row with the most recent timestamp.

The only flaw that I currently see is, that if an Employee is inserted that there is no matching row in the PensionScheme table. Though I am thinking of solving this with and INSERT trigger to add a default row.

I am really just looking for thoughts on this design. I am quite inexperienced with change tracking in databases.

bbartels
  • 355
  • 3
  • 9

1 Answers1

2

You might be interested in system versioning functionality available in MariaDB starting from the version 10.3.4-beta.

The basic idea is this (although you will of course need to tune the structure according to your real needs):

MariaDB [test]> CREATE TABLE PensionScheme (
                  ID INT PRIMARY KEY, 
                  EmpID INT, 
                  IsActive BOOLEAN WITH SYSTEM VERSIONING, 
                  ModifiedBy INT, 
                  EffectiveFrom DATETIME
                );
Query OK, 0 rows affected (0.17 sec)

MariaDB [test]> INSERT INTO PensionScheme VALUES (1,2,0,1,NULL);
Query OK, 1 row affected (0.05 sec)

MariaDB [test]> SELECT * FROM PensionScheme WHERE EmpID = 2;
+----+-------+----------+------------+---------------+
| ID | EmpID | IsActive | ModifiedBy | EffectiveFrom |
+----+-------+----------+------------+---------------+
|  1 |     2 |        0 |          1 | NULL          |
+----+-------+----------+------------+---------------+
1 row in set (0.00 sec)

MariaDB [test]> UPDATE PensionScheme 
                  SET IsActive = 1, ModifiedBy = 2 WHERE EmpID = 2;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Inserted: 1  Warnings: 0

MariaDB [test]> SELECT * FROM PensionScheme WHERE EmpID = 2;
+----+-------+----------+------------+---------------+
| ID | EmpID | IsActive | ModifiedBy | EffectiveFrom |
+----+-------+----------+------------+---------------+
|  1 |     2 |        1 |          2 | NULL          |
+----+-------+----------+------------+---------------+
1 row in set (0.00 sec)

MariaDB [test]> SELECT ID, IsActive, ModifiedBy, row_start, row_end 
                  FROM PensionScheme FOR system_time ALL WHERE EmpID = 2;
+----+----------+------------+----------------------------+----------------------------+
| ID | IsActive | ModifiedBy | row_start                  | row_end                    |
+----+----------+------------+----------------------------+----------------------------+
|  1 |        0 |          1 | 2018-01-28 14:59:54.955159 | 2018-01-28 15:00:56.430942 |
|  1 |        1 |          2 | 2018-01-28 15:00:56.430942 | 2038-01-19 05:14:07.999999 |
+----+----------+------------+----------------------------+----------------------------+
2 rows in set, 3 warnings (0.00 sec)

MariaDB [test]> UPDATE PensionScheme SET EffectiveFrom = NOW() WHERE EmpID = 2;
Query OK, 1 row affected (0.06 sec)
Rows matched: 1  Changed: 1  Inserted: 0  Warnings: 0

MariaDB [test]> SELECT ID, IsActive, ModifiedBy, row_start, row_end 
                  FROM PensionScheme FOR system_time ALL WHERE EmpID = 2;
+----+----------+------------+----------------------------+----------------------------+
| ID | IsActive | ModifiedBy | row_start                  | row_end                    |
+----+----------+------------+----------------------------+----------------------------+
|  1 |        0 |          1 | 2018-01-28 14:59:54.955159 | 2018-01-28 15:00:56.430942 |
|  1 |        1 |          2 | 2018-01-28 15:00:56.430942 | 2038-01-19 05:14:07.999999 |
+----+----------+------------+----------------------------+----------------------------+
2 rows in set, 3 warnings (0.00 sec)

MariaDB [test]> SELECT * FROM PensionScheme WHERE EmpID = 2;
+----+-------+----------+------------+---------------------+
| ID | EmpID | IsActive | ModifiedBy | EffectiveFrom       |
+----+-------+----------+------------+---------------------+
|  1 |     2 |        1 |          2 | 2018-01-28 15:03:19 |
+----+-------+----------+------------+---------------------+
1 row in set (0.00 sec)
elenst
  • 3,839
  • 1
  • 15
  • 22