Enligt min erfarenhet, när utvecklare försöker göra sitt system riktigt "dynamiskt" försöker de faktiskt koda för problem som de inte har tänkt på ännu. Det är vanligtvis en dålig väg att ta. Är det verkligen så mycket extra arbete för en modul att inkludera två tabeller istället för en?
I varje fall där jag har sett mönstret (eller anti-mönster?) att försöka göra ett generiskt "gör allt"-bord har det fallit platt på ansiktet. RDBMS fungerar bäst med väldefinierade problemområden. Om modulen har ett behov av att behålla historik bör modulen lägga till en historiktabell som passar själva tabellen. Detta har också en stor fördel genom att du på vägen sannolikt vill behålla olika typer av information i historiken beroende på vilken tabell eller modul som historiken sparas för. Om du har en generisk historiktabell blir det mycket svårare.
Om du nu helt enkelt vill fånga den sista användaren för att uppdatera eller infoga ett visst objekt (tabellrad) och det kan vara i flera tabeller kan du använda ett arvsmönster där du har en överordnad tabell och flera underordnade tabeller. Till exempel:
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)
)