Het volgende is hoe ik het zou doen. Ik heb nog wat opmerkingen onderaan nadat je het schema hebt gezien.
Log
LogID - unieke log-ID
Tijd - datum/tijd van evenement
LogType - String of ID
(commentaar aan de zijkant, ik zou hier een id gebruiken, zodat je een onderstaande berichtentabel kunt gebruiken, maar als je snel en vies wilt, kun je gewoon een unieke tekenreeks voor elke logtijd gebruiken (bijv. "Game Started", "Message Sent" , enz.)
LogActor
LogID - externe sleutel
LogActorType - String of ID (zoals hierboven, als ID heb je een opzoektabel nodig)
LogActorID - Dit is een unieke id voor de tabel voor het type bijv. Gebruiker, Groep, Spel
Opeenvolging - dit is een volgorde van de acteurs.
LogMessage
LogType - externe sleutel
Bericht - lange reeks (varchar(max)?)
Taal - string(5) zodat u verschillende talen kunt uitschakelen, bijv. "US-en"
Voorbeeldgegevens (met uw 3 voorbeelden)
Logboek
ID Time LogType
1 1/1/10 1
2 1/1/10 2
3 1/1/10 3
LogActor
LogID LogActorType LogActorID Sequence
1 User 1 1
1 User 2 2
2 User 1 1
2 User 2 2
2 User 2 3
2 Game 1 4
3 User 3 1
3 Group 1 2
LogMessage
LogType Message
1 {0} Made a new friend {1}
2 {0}, {1}, {2} played a game ({3})
3 {0} joined a group ({1})
Gebruiker
ID Name
1 User A
2 User B
3 User C
Spel
ID Name
1 Name of game
Groep
ID Name
1 Name of group
Dus hier zijn de leuke dingen over dit ontwerp.
-
Het is heel eenvoudig uit te breiden
-
Het behandelt meertalige problemen onafhankelijk van de acteurs
-
Het documenteert zichzelf, de LogMessage-tabel legt precies uit wat de gegevens die u opslaat moeten zeggen.
Enkele slechte dingen erover.
-
Je moet wat ingewikkelde bewerkingen uitvoeren om de berichten te lezen.
-
Je kunt niet zomaar naar de database kijken en zien wat er is gebeurd.
In mijn ervaring wegen de goede kanten van dit soort ontwerp op tegen de slechte dingen. Wat ik heb gedaan om me in staat te stellen snel en vies naar het logboek te kijken, is een weergave maken (die ik niet gebruik voor de applicatiecode) die ik kan bekijken wanneer ik moet zien wat er aan de hand is via de achterkant einde.
Laat het me weten als je vragen hebt.
Update - Enkele voorbeeldvragen
Al mijn voorbeelden staan in sqlserver 2005+, laat het me weten als er een andere versie is die ik moet targeten.
Bekijk de LogActor-tabel (er zijn een aantal manieren om dit te doen, de beste hangt van veel dingen af, waaronder gegevensdistributie, gebruiksscenario's, enz.) Hier zijn er twee:
a)
SELECT
LogId,
COLLESCE(U.Name,Ga.Name,Go.Name) AS Name,
Sequence
FROM LogActor A
LEFT JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
LEFT JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
LEFT JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
ORDER BY LogID, Sequence
b)
SELECT
LogId,
U.Name AS Name,
Sequence
FROM LogActor A
INNER JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
UNION ALL
SELECT
LogId,
Ga.Name AS Name,
Sequence
FROM LogActor A
INNER JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
UNION ALL
SELECT
LogId,
Go.Name AS Name,
Sequence
FROM LogActor A
INNER JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
ORDER BY LogID, Sequence
Over het algemeen denk ik dat a) beter is dan b) Als je bijvoorbeeld een acteur mist, zal type a) het opnemen (met een null-naam). Echter b) is gemakkelijker te onderhouden (omdat de UNION ALL-statements het meer modulair maken). Er zijn andere manieren om dit te doen (bijv. CTE, views, enz.). Ik ben geneigd om het te doen zoals b) en van wat ik heb gezien, lijkt dat op zijn minst de standaardpraktijk te zijn, zo niet de beste praktijk.
Dus de laatste 10 items in het logboek zien er ongeveer zo uit:
SELECT
LogId,
M.Message,
COLLESCE(U.Name,Ga.Name,Go.Name) AS Name,
Time,
A.Sequence
FROM Log
LEFT JOIN LogActor A ON Log.LogID = A.LogID
LEFT JOIN User U ON A.LogActorID = U.[ID] AND LogActorType = "User"
LEFT JOIN Game Ga ON A.LogActorID = Ga.[ID] AND LogActorType = "Game"
LEFT JOIN Group Go ON A.LogActorID = Go.[ID] AND LogActorType = "Group"
LEFT JOIN LogMessage M ON Log.LogType = M.LogMessage
WHERE LogID IN (SELECT Top 10 LogID FROM Log ORDER BY Date DESC)
ORDER BY Date, LogID, A.Sequence
NB - Zoals je ziet is het makkelijker om alle log items van een datum te selecteren dan de laatste X, omdat we hiervoor een (waarschijnlijk zeer snelle) subquery nodig hebben.