sql >> Database >  >> RDS >> Mysql

Databases:een logboek maken van acties, hoe om te gaan met verschillende referenties?

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.



  1. Twee tabellen samenvoegen met een verschillend aantal kolommen

  2. Mysql - rijen vullen voor ontbrekende maanden

  3. Actieve verbindingen sluiten met RMySQL

  4. HTML-tags ontbreken bij SELECT uit MySQL (Codeigniter)