Mijn ervaring is dat wanneer ontwikkelaars hun systeem echt "dynamisch" proberen te maken, ze eigenlijk proberen te coderen voor problemen waar ze nog niet aan hebben gedacht. Dat is meestal een slechte weg om te nemen. Is het echt zoveel extra werk voor een module om twee tabellen op te nemen in plaats van één?
In alle gevallen waarin ik het patroon (of het antipatroon?) heb gezien van het maken van een generieke "doet alles"-tabel, is het plat op zijn gezicht gevallen. RDBMS'en werken het beste met goed gedefinieerde probleemgebieden. Als de module geschiedenis moet bijhouden, moet de module een geschiedenistabel toevoegen die bij de tabel zelf past. Dit heeft ook een enorm voordeel, omdat u later waarschijnlijk verschillende soorten informatie in de geschiedenis wilt bewaren, afhankelijk van de tabel of module waarvoor de geschiedenis wordt bewaard. Als je een algemene geschiedenistabel hebt, wordt dat veel moeilijker.
Als u nu eenvoudig de laatste gebruiker wilt vastleggen om een bepaald item (tabelrij) bij te werken of in te voegen en dat kan in meerdere tabellen zijn, dan kunt u een overervingspatroon gebruiken waarbij u een bovenliggende tabel en meerdere onderliggende tabellen hebt. Bijvoorbeeld:
CREATE TABLE Audited_Items
(
id INT NOT NULL IDENTITY,
CONSTRAINT PK_Audited_Items PRIMARY KEY CLUSTERED (id)
)
CREATE TABLE Articles
(
id INT NOT NULL,
[Article specific columns]
CONSTRAINT PK_Articles PRIMARY KEY CLUSTERED (id),
CONSTRAINT FK_Articles_Audited_Items FOREIGN KEY (id) REFERENCES Audited_Items (id)
)
CREATE TABLE Media
(
id INT NOT NULL,
[Media specific columns]
CONSTRAINT PK_Media PRIMARY KEY CLUSTERED (id),
CONSTRAINT FK_Media_Audited_Items FOREIGN KEY (id) REFERENCES Audited_Items (id)
)
CREATE TABLE Audit_Trail
(
audited_item_id INT NOT NULL,
audit_datetime DATETIME NOT NULL,
user_id INT NOT NULL,
[audit columns]
CONSTRAINT PK_Audit_Trail PRIMARY KEY CLUSTERED (audited_item_id, audit_datetime),
CONSTRAINT FK_Audit_Trail_Audited_Items FOREIGN KEY (audited_item_id) REFERENCES Audited_Items (id)
)