Please have a look at the DDL below:
CREATE TABLE Sport (ID int, Description varchar(50),primary key(ID))
CREATE TABLE Audit (AditID int, PersonID int, SportID int, AuditDate datetime,primary key(id))
CREATE Table Person (ID int not null, Name varchar(50), FavouriteSportID int, PRIMARY KEY (id),
FOREIGN KEY (FavouriteSportID) REFERENCES Sport(Id))
INSERT INTO Sport VALUES (1,'Football')
INSERT INTO Sport VALUES (2,'Basketball')
INSERT INTO Sport VALUES (3,'Squash')
INSERT INTO Person VALUES (1,'Ian',1)
INSERT INTO Audit VALUES (1,1,1,'2012-01-01')
INSERT INTO Audit VALUES (2,1,1,'2012-02-01')
INSERT INTO Audit VALUES (3,1,'2012-03-01')
The Audit table shows the Persons favorite sport in the past.
I am conscious that this involves storing the favorite sport in two places i.e. Person.FavouriteSportID and the most recent audit record i.e. audit record ID 3 also shows that Ian’s current favorite sport is Squash (because it has the most recent audit record).
I am wondering if there is a better design for this simple requirement.
It’s fine. It’s good, in fact.
Alternatively, you could use AuditId in place of SportId in Person, as a reference to the latest audit row with the current
SportId, but that makes Audit an active part of the current representation. I like your design better, since the current representation is confined to fewer tables, and the audit table is an outrigger. It’s also much easier to automate–a simpleafter update, deletetrigger on Person will reliably maintain the audit table with no further effort from anybody.EDIT
If you don’t need to record the current association in the audit table, then don’t, and you haven’t stored the same info twice. As mentioned, an
after update, delete triggerwill do nicelyIf you do need to record the current association in the audit table, it’s not quite as clean, but
Auditis still an outrigger and you still can automate it with anafter insert, updatetrigger: