Lo siguiente es cómo lo haría. Tengo algunos comentarios más en la parte inferior después de haber visto el esquema.
Iniciar sesión
LogID - ID de registro único
Hora - fecha/hora del evento
LogType - Cadena o ID
(comentario adicional, usaría una identificación aquí para que pueda usar una tabla de mensajes que se muestra a continuación, pero si quiere algo rápido y sucio, puede usar una cadena única para cada tiempo de registro (p. ej., "Juego iniciado", "Mensaje enviado"). , etc.)
LogActor
LogID - clave externa
LogActorType - Cadena o ID (como arriba, si es ID necesitará una tabla de búsqueda)
LogActorID:esta es una identificación única para la tabla para el tipo, por ejemplo, Usuario, Grupo, Juego
Secuencia:este es un orden de los actores.
Mensaje de registro
LogType - clave externa
Mensaje - cadena larga (varchar(max)?)
Idioma:cadena (5) para que pueda seleccionar diferentes idiomas, por ejemplo, "US-en"
Datos de ejemplo (usando sus 3 ejemplos)
Iniciar sesión
ID Time LogType
1 1/1/10 1
2 1/1/10 2
3 1/1/10 3
Actor de registro
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
Mensaje de registro
LogType Message
1 {0} Made a new friend {1}
2 {0}, {1}, {2} played a game ({3})
3 {0} joined a group ({1})
Usuario
ID Name
1 User A
2 User B
3 User C
Juego
ID Name
1 Name of game
Grupo
ID Name
1 Name of group
Estas son las cosas buenas de este diseño.
-
Es muy fácil de extender
-
Maneja problemas multilingües independientemente de los actores
-
Es autodocumentado, la tabla LogMessage explica exactamente lo que deben decir los datos que está almacenando.
Algunas cosas malas al respecto.
-
Tienes que hacer un procesamiento complicado para leer los mensajes.
-
No puede simplemente mirar la base de datos y ver qué sucedió.
En mi experiencia, las partes buenas de este tipo de diseño superan las partes malas. Lo que he hecho para permitirme hacer una mirada rápida y sucia al registro es hacer una vista (que no uso para el código de la aplicación) que puedo ver cuando necesito ver lo que está pasando en la parte posterior. fin.
Hazme saber si tienes preguntas.
Actualización:algunas consultas de ejemplo
Todos mis ejemplos están en sqlserver 2005+, avíseme si hay una versión diferente a la que desea que apunte.
Ver la tabla de LogActor (hay varias formas de hacer esto, la mejor depende de muchas cosas, incluida la distribución de datos, los casos de uso, etc.). Estas son dos:
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
En general, creo que a) es mejor que b). Por ejemplo, si falta un actor, escriba a) lo incluirá (con un nombre nulo). Sin embargo, b) es más fácil de mantener (porque las declaraciones UNION ALL lo hacen más modular). Hay otras formas de hacerlo (por ejemplo, CTE, vistas, etc.). Me inclino a hacerlo como b) y, por lo que he visto, parece ser al menos una práctica estándar, si no la mejor práctica.
Entonces, los últimos 10 elementos en el registro se verían así:
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:como puede ver, es más fácil seleccionar todos los elementos de registro de una fecha que la última X, porque necesitamos una subconsulta (probablemente muy rápida) para esto.