El otro día en un curso de Business Intelligence surgió un caso como este.
Imaginaos que tenemos una base de datos donde almacenamos información al respecto de proveedores, clientes, trabajadores, representantes y convocatorias.
En un momento dado se quieren enviar invitaciones a los diferentes proveedores, clientes… y se quiere tener constancia a nivel de base de datos de quiénes han sido invitados a cada convocatoria.
No sé por qué me vino a la cabeza inmediatamente una solución orientada a objetos, así que intenté plasmar la idea a nivel de modelo relacional, surgiendo algo similar a esto:
Como véis, la herencia se ve a simple vista. La clase invitado es una clase abstracta de la cual heredan tanto el representante, como el proveedor, cliente y trabajador. Para resolver la herencia a nivel de modelo relacional las cuatro tablas inferiores guardan foreign key contra invitado. Además podréis ver que en la tabla LINEA_CONVOCATORIA se tiene referencia a la tabla INVITADO, con esto hacemos algo similar a pasar a un método por parámetro la clase abstracta, para que luego en tiempo de compilación, y segíºn el objeto que se pase (y que obligatoriamente tendrá que heredar de invitado), se actue en consecuencia.
¿Problemas de esto? Mantener a base de datos puede ser como mínimo extraño. El campo CO_INVITADO de todas las tablas debería admitir NULL (por cierto hay una errata en el diagrama al respecto ya que como podéis ver es NOT NULL, y por eso la cardinalidad hacia INVITADO aparece siempre como 1, cuando debería ser 0..1). Además, fijaros en el detalle de que la tabla INVITADO tiene un campo llamado TABLA. Allí almacenaríamos el nombre de la tabla donde realmente está el invitado… jejeje, aquí es donde se pierde la historia y me deja de gustar el tema, pero es la íºnica manera que se me ocurrió resolver de dónde sacar de dónde viene el invitado cuando empezamos a buscar a partir de la tabla LINEA_CONVOCATORIA, es decir, lo que sería en tiempo de compilación que se te pasara un objeto INVITADO y resolver dependiendo de si el objeto es un proveedor, cliente…
Esto solución resulta como mínimo curiosa. ¿Se os ocurre cómo mejorarla? ¿Proponéis alternativas?
En el curso se dijo de resolver esto a nivel de Triggers, y dejarse de historias. A mi sinceramente, no me gustan los Triggers, pero eso no quiere decir que no sean la mejor forma de resolver este tipo de problemas.
Saludos!
Miguel.
Hola he leido tu articulo y he pensado otra posible solución a lo del campo tabla. Una solución alternativa que se me ocurre es parametrizar, por ejemplo podriamos asignar el grupo 001 -> 100 para los representantes, 101-> 200 para proveedores etc..
Saludos
Sirve, claro, pero tiene el problema de que si tenemos más ocurrencias que el rango definido para cada una de las entidades con las que contamos (representantes, proveedores…) entonces el sistema falla… y lo peor es cómo lo redefinimos sobre la marcha para aumentar el rango… eso sería más complicado aíºn resolverlo porque los rangos superiores estarían copados por las otras entidades. Podríamos jugar con rangos más grandes y con mayor separación entre ellos, pero al final ante un níºmero infinito de inserciones siempre existiría un caso que tendríamos que ampliar.
Gracias por la aportación!
La herencia es un tema complicado en BBDD y tal vez no haya una solución que nos nos deje del todo conformes… La solución que propones también se me había ocurrido, a pesar de eso seguí buscando para ver si alguien tenía la solución mágica (simple e intuitiva) …
Sólo por aportar algo diferente (si quisiéramos quitar el atributo TABLA), con sus ventajas y desventajas, se podría quitar el atributo TABLA de la tabla de invitados y colocarle 4 claves foráneas (de las cuales solo una sería NO NULA, y las demás nulas) y quitar las claves foráneas de las tablas hijas.
Gracias por la aportación Raúl.
Buenas, creo que el manejo de la herencia se especifica mas en el modelo de diseño, no asi en la entidad relación, de todas maneras puede trasladarse de alguna manera y siempre va a depender del objetivo que tenga la aplicación.
Yo lo solucionaría casi idénticamente, en la tabla invitado tendría un FK idInvitado que se relacione la tabla TipoInvitado que contendrá toda la la lista de posibles invitados. Ahora, la relación existentes entre estos tipos de invitados y sus respectivas tablas que heredan de la tabla padre invitado, la realizaría a nivel lógico.
Estimados,
Cuando se realiza una búsqueda es inevitable hacer un join en dos tablas por ejemplo si quieres obtener los clientes que fueron invitados tendrías que hacer un join con clientes e invitados.
Otra alternativa es tener una sola tabla en nuestra base de datos que va a tener todos las columnas de las tablas hijas y en esta agregar una columna la que nos va a indicar si es un cliente, proveedor, etc. Por lo general esta solución es la mas eficiente al momento de consultas, dado que no es necesario realizar ningun join y no tendrias ninguna FK. La desventaja es que si es un cliente va a tener los campos de proveedor vació. Dependiendo de el motor te permite configurar para que los campos que estén en nulo no te consuma espacio.
Saludos,