Context
I have 3 entities (user, shop and car), a car can only have one regNum
, one shopId
and one ownerId
at a time, that's why they are embedded in the car table.
create table "user"
(
id bigint primary key,
name varchar(40) not null
);
create table "shop"
(
id bigint primary key,
name varchar(40) not null
);
create table "car"
(
id bigint primary key,
ownerId bigint,
regNum varchar(8),
shopId bigint,
price numeric(10,2),
constraint foreign key(ownerId) references "user",
constraint foreign key(shopId) references "shop"
);
Problem
I want to keep history of the car's regNum
, ownerId
, shopId
and eventually other future fields (but not necessarily all of them).
What's the best solution (scalability/performance/easeOfUse) ? I have found the ones below, maybe someone has faced the same problem, maybe there is another solution ?
Solution 1
I add as much history tables as I have fields to "watch".
This seems to be a normalized way to do the job but it also looks pretty complex to maintain, it's also more greedy as if I modify all fields at once (regNum, shopId and ownerId), I need to insert 3 records (one for each history and so on if I watch other fields later).
create table "carOwner"
(
id bigint primary key,
carId bigint not null,
changedAt timestamp not null,
ownerId bigint,
constraint foreign key(carId) references "car",
constraint foreign key(ownerId) references "user"
);
create table "carShop"
(
id bigint primary key,
carId bigint not null,
changedAt timestamp not null,
shopId bigint,
constraint foreign key(carId) references "car",
constraint foreign key(shopId) references "shop"
);
create table "carRegNum"
(
id bigint primary key,
carId bigint not null,
changedAt timestamp not null,
regNum varchar(8),
constraint foreign key(carId) references "car"
);
Solution 2
I keep history in a single table, which is a light snapshot of the car
table at a given time. It seems easier to maintain but it's not precise as I cannot directly see what changed if I don't have previous record.
create table "carHistory"
(
id bigint primary key,
carId bigint not null,
changedAt timestamp not null,
ownerId bigint,
regNum varchar(8),
shopId bigint,
constraint foreign key(carId) references "car",
constraint foreign key(shopId) references "shop",
constraint foreign key(ownerId) references "user"
);
Best Answer
Not sure I understand your initial design:
If for example, a car_owner is not mandatory, you may consider moving it to a separate entity:
The history for the owner of a car:
car_owner_history can be maintained via triggers. When a car is assigned it's first owner
This results in the following change in history
When car changes owner from o_1 to o_2
The following change is made in history:
When a car no longer has an owner end_time is updated to reflect that.
Who owned car c1 at time t_x?
What owners have car c_1 had?