Vamos a ver el paso del MER a tablas o también el paso de tablas a MER. En todos los libros, el modelo de trabajo es: partiendo de la especificación de requisitos realizamos el MER; del MER obtenemos de manera automatizada las tablas y con estas hacemos la BD, también de manera automatizada. Sin embargo, hay diseñadores a los que les gusta hacer directamente las tablas, sobre todo si el problema no es muy grande. A veces, en este último caso hay que hacer el MER, porque estamos en una prueba (oposición, prueba para obtener un trabajo, etc) o porque el cliente nos lo exige, en este último caso, hay diseñadores que a partir de las tablas, obtienen el MER. En este documento veremos tanto del paso de MER a tablas como el de tablas a MER.
En color azul: atributos que añadimos a las tablas para representar una relación.
En color rojo: partes del MER que no pueden expresar las tablas.
En color verde: pasos que debemos seguir para convertir una relación en tablas.
CP: Clave Principal
CAJ: Clave Ajena
CALT: Clave Alternativa
VNN: Valores no nulos
UNIQUE: Valores únicos (índice)
MER: Modelo Entidad Relación
Las CP se han definido como VNN ya que es lo que dice el estándar SQL, aunque en MySQL no es obligatorio hacerlo.
Suponemos que nuestro SGBD tiene disponibles las restricciones de integridad de CP, CAJ, CALT, VNN y UNIQUE.
VNN → No permite valores nulos
UNIQUE → No permite valores repetidos, pero sí permite nulos
CP → UNIQUE + VNN
CALT → CP
CAJ → El valor debe estar en el campo y la tabla referenciados. Sí permite nulos.
Dependiendo del SGBD que usemos, incluso del motor de BD dentro de ese SGBD podemos tener más o menos restricciones de integridad disponibles.
EMPLEADO (
DNI VARCHAR(10) VNN
Nombre VARCHAR(50) VNN
Ape_1 VARCHAR(50) VNN
Ape_2 VARCHAR(50) VNN
NSS VARCHAR(10) VNN
Fecha_nac DATE()
Sueldo: Decimal(7,2)
Telefono VARCHAR(12)
CP(DNI)
UNIQUE(NSS)
)
El atributo Teléfono no lo hemos hecho multivaluado. Veremos más adelante cómo conseguirlo.
Empleado (
IdEmp INT VNN
Nombre VARCHAR(50) VNN
CP(IdEmp)
Puesto (
IdP INT VNN
Desc VARCHAR(50)
CP(IdP)
)
Ocupa (
Empleado: INT VNN
Puesto: INT VNN
Turno: VARCHAR(50) VNN
CP(Empleado,Puesto)
CAJ Empleado->Empleado.IdEmp
CAJ Puesto ->Puesto.CodP
)
NOTAS:
Resumen:
La solución es exáctamente igual que la anterior ya que en ningún caso podemos representar las restricciones 1,N con las restricciones que tenemos disponible. Como norma general, no se usarán restricciones 1,N, pero si es imprescindible, tendremos que hacer que esa restricción se cumpla desde la aplicación o desde disparadores en la propia BD.
Para que esta restricción se cumpla desde la aplicación debemos comprobar que:
Es el mismo caso anterior pero con la restricción 1,M, que no se puede cumplir al otro lado.
Al igual que en los dos casos anteriores, la restricciones 1,N y 1,M no se pueden cumplir.
En las relaciones muchos a muchos la CP es la unión de las dos CPs de las tablas relacionadas.
En todas las relaciones muchos a muchos debemos preguntarnos si la CP es correcta o debemos expandirla añadiendo otros atributos.
Por ejemplo, supongamos la relación muchos a muchos entre las entidades Autor y Libro en la que un autor puede escribir cero o muchos libros y un libro puede haber sido escrito por cero o muchos autores. Se ha añadido el atributo opcional NumeroDeOrden que cuando un libro ha sido escrito por varios autores, nos indica el número de orden en el que cada autor aparece en el libro (ese número de orden es importante).
En este caso debemos preguntarnos si un autor concreto puede escribir un libro concreto más de una vez. Como la respuesta más razonable es que no, podemos dejar la CP de la nueva tabla Escribe como la unión de las CP de las dos tablas relacionadas:
Autor (
IdAutor INT VNN
Nombre VARCHAR(50) VNN
CP(IdAutor)
Libro (
IdLibro INT VNN
Titulo VARCHAR(50) VNN
CP(IdLibro)
)
Escribe (
Autor INT VNN
Libro INT VNN
NumeroDeOrden INT
CP(Autor,Libro)
CAJ Autor->Autor.IdAutor
CAJ Libro->Ejemplar.IdEjemplar
)
Esto no siempre es así. Consideremos ahora una biblioteca en la que un usuario puede sacar cero o muchos ejemplares de un libro en préstamo y un ejemplar puede haber sido sacado por cero o muchos usuarios de la biblioteca. Cuando un ejemplar de un libro es sacado en préstamo nos interesa saber la fecha de préstamo, que es un atributo obligatorio, y la fecha de devolución, que inicialmente es nulo hasta que se devuelve el libro.
En este caso, el modelo lógico quedaría:
Usuario (
IdUsuario INT VNN
Nombre VARCHAR(50) VNN
CP(IdUsuario)
Ejemplar (
IdEjemplar INT VNN
Estado VARCHAR(50)
CP(IdEjemplar)
)
Prestamo (
Autor INT VNN
Ejemplar INT VNN
FechaPrestamo Date VNN
FechaDevolucion Date
CP(Autor,Ejemplar)
CAJ Autor-> Autor.IdAutor
CAJ Ejemplar->Ejemplar.IdEjemplar
)
Como en el caso anterior, debemos preguntarnos si es necesario ampliar la CP de la nueva tabla: ¿Es posible que un mismo usuario saque más de una vez el mismo ejemplar de un libro? En este caso la respuesta es afirmativa, por lo que es necesario ampliar la CP.
El nuevo modelo entidad-relación, quedaría así:
Y la tabla préstamo:
Prestamo (
Autor INT VNN
Ejemplar INT VNN
FechaPrestamo Date VNN
FechaDevolucion Date
CP(Autor,Ejemplar,FechaPrestamo)
CAJ Autor-> Autor.IdAutor
CAJ Ejemplar->Libro.IdEjemplar
)
Como antes, cabe preguntarse ahora: ¿Es posible que un mismo usuario saque más de una vez el mismo ejemplar de un libro en la misma fecha? Si la respuesta es afirmativa, tendríamos que volver a amplicar la CP.
En los casos en los que la CP es demasiado compleja, se puede simplificar con un campo nuevo autonumérico de la siguiente manera:
Prestamo (
IdPrestamo INT VNN AUTONUMERICO
Autor INT VNN
Ejemplar INT VNN
FechaPrestamo Date VNN
FechaDevolucion Date
CP(IdPrestamo)
CAJ Autor-> Autor.IdAutor
CAJ Ejemplar->Libro.IdEjemplar
)
Empleado (
IdEmp INT VNN
Nombre VARCHAR(50) VNN
CP(IdEmp)
Puesto (
IdP INT VNN
Desc VARCHAR(50)
Empleado INT #Ocupa
CP(IdP)
CAJ Empleado->Empleado.IdEmpleado #Ocupa
)
En este caso indicamos con el comentario #Ocupa los cambios que hemos hecho en las tablas para representar la relación Ocupa.
Resumen:
Empleado (
IdEmp INT VNN
Nombre VARCHAR(50) VNN
CP(IdEmp)
Puesto (
IdP INT VNN
Desc VARCHAR(50)
Empleado INT VNN #Ocupa
CP(IdP)
CAJ Empleado->Empleado.IdEmpleado #Ocupa
)
Es el mismo caso anterior y se hace igual, pero para conseguir la cardinalidad mínima uno del lado uno, esto es, que todo puesto tenga asignado un empleado no permitiremos dejar a nulo la clave ajena poniendo VNN.
Resumen:
Como ya hemos comentado anteriormente, la restricción 1,N no podemos conseguirla. Por lo tanto se resuelve como una relación (0,1)-(0,N) y se deberá controlar la cardinalidad mínima uno en la aplicación o mediante disparadores en la BD tal y como se explicó en la relaciones N:M.
Se resuelve como una relación (1,1)-(0,N) y no podemos conseguir la cardinalidad mínima 1 del lado muchos.
No es normal encontrarnos con relaciones 1:N con atributos propios de la relación. Veamos el siguiente ejemplo:
Poniendo el atributo Turno en la relación indicamos que no pertenece a la entidad Puesto, es decir: no es cierto que cada puesto tiene un turno. Tampoco lo ponemos en la entidad empleado con lo que tampoco debe ocurrir que cada empleado tenga un turno. Al poner el atributo Turno en la relación estamos indicando que sólo debe existir un turno cuando algún empleado esté ocupando un puesto y, en este caso, debe ser obligatorio (ya que lo hemos puesto con linea continua).
Casi siempre, este tipo de atributos se suelen poner en el lado muchos de la relación. Si fuese imprescindible ponerlo en la relación y hacer que se cumpla deberemos hacerlo mediante programación o usando una solución un poco más compleja, es decir creando una nueva tabla:
Empleado (
IdEmp INT VNN
Nombre VARCHAR(50) VNN
CP(IdEmp)
Puesto (
IdP INT VNN
Desc VARCHAR(50)
CP(IdP)
)
Ocupa (
Empleado: INT VNN
Puesto: INT VNN
Turno: VARCHAR(50) VNN
CP(Puesto)
CAj (Empleado->DNI)
CAj (Puesto->CodP)
)
Las relaciones uno a uno son difíciles de encontrar y muchas veces responden a la necesidad de dividir una tabla en dos para tener un acceso muy rápido a ella guardándola en memoria RAM y manteniendo la otra parte que pesará mucho más en disco. También se puede dividir una tabla en dos para aplicales a cada una diferentes requerimientos, por ejemplo de copia de seguridad.
Empleado (
IdEmp INT VNN
Nombre VARCHAR(50) VNN
CP(IdEmp)
Puesto (
IdP INT VNN
Desc VARCHAR(50)
Empleado INT #Ocupa
CP(IdP)
CALT(Empleado) #Ocupa
CAJ Empleado->Empleado.IdEmpleado #Ocupa
)
Resumen:
Este es el mismo caso anterior, pero definiremos la CAJ como VNN para asegurarnos que todo ejemplar de Puesto tendrá asignado como mínimo un empleado.
Empleado (
IdEmp INT VNN
Nombre VARCHAR(50) VNN
CP(IdEmp)
Puesto (
IdP INT VNN
Desc VARCHAR(50)
Empleado INT VNN #Ocupa
CP(IdP)
CALT(Empleado) #Ocupa
CAJ Empleado->Empleado.IdEmpleado #Ocupa
)
Resumen:
Es el mismo caso anterior, pero dándole la vuelta.
Empleado (
IdEmp INT VNN
Nombre VARCHAR(50) VNN
Puesto INT VNN #Ocupa
CP(IdEmp)
CALT(Puesto) #Ocupa
CAJ Puesto->Puesto.IdP #Ocupa
Puesto (
IdP INT VNN
Desc VARCHAR(50)
CP(CodP)
)
Una de las opciones es hacerla igual que la relación (1,1)-(0,1) y conseguir mediante la aplicación o mediante un disparador en la BD que se cumpla la otra cardinalidad mínima.
Otra solución consiste en juntar todos los atributos en una sóla tabla, pero claro, si hemos separado las tablas intencionadamente, no sirve.
EmpleadoPuesto (
IdEmp INT VNN
Nombre VARCHAR(50) VNN
IdP INT VNN
Desc VARCHAR(50)
CP(IdEmp)
CALT(IdP)
)
Resumen:
Tal y como vimos en las Relaciones 1:N con atributos, también es muy infrecuente poner atributos a las relaciones 1:1. En estos casos, se suele trasladar a alguna de las dos entidades participantes en la relación.
En la notación clásica de Chen se representa la dependencia de existencia por las letras Ex dentro del rombo de la relación y marcando la entidad débil con un doble cuadro. La entidad débil es la que necesita de la otra para existir. En el caso de una biblioteca está claro que para que exista un ejemplar de El Quijote es necesario que ese libro esté dado de alta, sin embargo si que sería posible tener El Quijote como libro, pero no disponer momentáneamente de ningún ejemplar porque han resultado dañados por ejemplo.
En la notación min-max dependencia de existencia ya viene representada por la cardinalidad 1,1. En este caso se indica que todo Ejemplar debe tener asociado como mínimo un libro, es decir, que para que exista un ejemplar, debe existir uno un sólo un libro con el que estará relacionado.
Como en la notación clásica de Chen no se ponían las cardinalidades mínimas, sólo se ponían las máximas, tuvieron que inventarse un método para representar esa cardinalidad mínima 1 que requiere la dependencia de existencia.
Por lo tanto, las dependencias de existencia las trataremos como una relación uno a muchos del tipo (1,1)-(0,N) normal.
Libro (
IdLibro INT VNN
Título VARCHAR(50) VNN
CP(IdLibro)
Ejemplar (
IdEjemplar INT VNN
Estado VARCHAR(50)
Libro INT VNN #Tiene
CP(IdEjemplar)
CAJ Libro->Libro.IdLibro #Tiene
)
En una dependencia de identificación, además de tener una dependencia de existencia, para identificar correctamente al Ejemplar necesitaremos identificar al Libro. Esto ocurre si numeramos los ejemplares de El Quijote como 1, 2, 3 y 4; y los ejemplares de La Celestina como 1, 2 y 3. Si le pedimos a alguien que nos traiga el ejemplar 2, nos responderá: “Vale, pero ¿de qué libro?”
La notación min-max no puede representar las dependencias de existencia, por lo que aunque usemos esta notación, si tenemos una dependencia de existencia deberemos indicarla, como mínimo poniendo Id en la relación. La entidad débil ya sabemos que es la que está en el lado muchos de la relación.
Para representar una dependencia de identificación la trataremos como una relación uno a muchos del tipo (1,1)-(0,N) normal pero ampliaremos la CP de la entidad débil con la CAJ de la relación:
Libro (
IdLibro INT VNN
Título VARCHAR(50) VNN
CP(IdLibro)
Ejemplar (
IdEjemplar INT VNN
Estado VARCHAR(50)
Libro INT VNN #Tiene
CP(IdEjemplar,Libro) #Tiene
CAJ Libro->Libro.IdLibro #Tiene
)
Como método general para transformar una relación reflexiva, la abriremos repitiendo la entidad para convertirla en una relación binaria y la trataremos como tal.
Desglosamos la relación y la tratamos como una relación (0,1)-(0,1) normal.
Persona (
DNI VARCHAR(10) VNN
Nombre VARCHAR(50) VNN
Mujer VARCHAR(10) (Está casada)
CP(DNI)
UNIQUE(Mujer) (Está casada)
CAJ Mujer->Perdona.DNI (Está casada)
Desglosamos la relación y la tratamos como una relación (1,1)-(0,N) normal. En este caso hemos preferido una cardinalidad mínima de uno para el lado uno de la relación. Esto quiere decir que todo empleado debe tener como mínimo un superior, por lo que el jefe supremo deberá ser jefe de sí mismo. Lo vemos con un ejemplo de las tablas:
| DNI | Nombre | Jefe |
|---|---|---|
| 101 | Luis | 101 |
| 102 | Ana | 101 |
| 103 | Pedro | 102 |
| 104 | Antonio | 103 |
| 105 | Juan | 102 |
| 106 | Julia | 105 |
Como podemos ver Luis debe ser jefe de sí mismo para poder asegurar que todo empleado tiene como mínimo un jefe.
Empleado (
DNI VARCHAR(10) VNN
Nombre VARCHAR(50) VNN
Jefe VARCHAR(10) VNN (Dirigir)
CP(DNI)
CAJ Jefe->Empleado.DNI (Dirigir)
Desglosamos la relación y la tratamos como una relación (0,N)-(0,M) normal.
Persona (
DNI VARCHAR(10) VNN
Nombre VARCHAR(50) VNN
CP(DNI)
)
Enseña (
Profesor VARCHAR(10) VNN
Alumno VARCHAR(10) VNN
CP(Profesor,Alumno)
CAJ Profesor->Persona.DNI
CAJ Alumno ->Persona.DNI
)
En algunos casos tendremos ya hecho el modelo lógico y necesitaremos obtener el modelo entidad-relación. Veamos unos ejemplos:
Las relaciones 1:N del modelo entidad-relación se pueden reconocer en el modelo lógico por la presencia de una CAJ. Siempre que encontremos una restricción de CAJ sobre un campo y que los valores de dicho campo se puedan repetir, esto es no es ni CP, ni CALT, ni UNIQUE tendremos una relación uno a muchos. La tabla donde está definida la CAJ es el lado muchos de la relación y la tabla a donde apunta la CAJ será el lado uno.
Empleado (
IdEmp INT VNN
Nombre VARCHAR(50) VNN
CP(IdEmp)
Puesto (
IdP INT VNN
Desc VARCHAR(50)
Empleado INT
CP(IdP)
CAJ Empleado->Empleado.IdEmpleado
)
En este ejemplo, vemos como Empleado tiene definida una restricción de CAJ. Además, Empleado no es ni CP, ni CALT, ni UNIQUE por lo que tenemos una relación uno a muchos en la que Puesto es el lado muchos y Empleado es el lado uno.
La cardinalidad mínima del lado muchos siempre será 0 y la del lado uno dependerá de si el atributo que tiene la restricción de CAJ tiene, además, la restricción de VNN.
Partiendo de las siguientes tres tablas
Empleado (
IdEmp INT VNN
Nombre VARCHAR(50) VNN
CP(IdEmp)
Puesto (
IdP INT VNN
Desc VARCHAR(50)
CP(IdP)
)
Ocupa (
Empleado: INT VNN
Puesto: INT VNN
Turno: VARCHAR(50) VNN
CP(Empleado,Puesto)
CAJ Empleado->Empleado.IdEmp
CAJ Puesto ->Puesto.CodP
)
y basándonos en lo visto en el punto anterior. Si para hacer el modelo entidad-relación creamos una entidad por cada tabla y establecemos las relaciones, nos quedaría algo así:
La mayoría de veces en las que tengamos dos relaciones 1,1 en un extremo y 0,N en el otro apuntando a una tabla, eso se suele traducir en el modelo entidad-relación como una relación muchos a muchos:
Pero no siempre tiene porqué ser así. Partiendo del siguiente caso:
Este es un caso evidente en el que las dos relaciones 1,1; 0,N son una única relación muchos a muchos:
Sin embargo sin en vez de tratarse de una biblioteca se trata de una editorial en la que el echo de escribir es algo muy importante de la cual queremos guardar información como la fecha en la que se empezó a escribir un libro, la fecha en la que se acabó de escribir y relaciones como las revisiones que ha tenido ese libro que está siendo escrito por uno de varios autores; por parte del editor. En casos más complejos como este, es posible que es quiera contemplar Escribe como una entidad en vez de como una relación muchos a muchos.
Las relaciones 1:1 son iguales que las 1:N, pero sobre la CAJ, además hay definida una restricción que normalmente será de UNIQUE, pero que también podría ser de CALT o CP. Así:
Empleado (
IdEmp INT VNN
Nombre VARCHAR(50) VNN
CP(IdEmp)
Puesto (
IdP INT VNN
Desc VARCHAR(50)
Empleado INT
CP(IdP)
CALT(Empleado)
CAJ Empleado->Empleado.IdEmpleado
)
Se convertirá en:
Las relaciones reflexivas , en general, se reconocen por haber una CAJ que apunta a la misma tabla:
Persona (
DNI VARCHAR(10) VNN
Nombre VARCHAR(50) VNN
Mujer VARCHAR(10) (Está casada)
CP(DNI)
UNIQUE(Mujer) (Está casada)
CAJ Mujer->Perdona.DNI (Está casada)
Se convierte en:
La excepción son las relaciones muchos a muchos reflexivas. A ver las tablas:
Persona (
DNI VARCHAR(10) VNN
Nombre VARCHAR(50) VNN
CP(DNI)
)
Enseña (
Profesor VARCHAR(10) VNN
Alumno VARCHAR(10) VNN
CP(Profesor,Alumno)
CAJ Profesor->Persona.DNI
CAJ Alumno ->Persona.DNI
)
y pasarlas al modelo entidad relación nos debería quedar algo parecido a este modelo entidad-relación:
Como ya hemos comentado en el apartado de las relaciones N:M, la estructura de dos relaciones (1,1)-(0,N) sobre la misma entidad representa una relación muchos a muchos, con lo que el modelo entidad relación final, quedaría así:
Entidades
Relaciones N:M
Relaciones 1:N
Relaciones 1:1
Dependencias de existencia e identificación
Relaciones reflexivas
Paso del modelo lógico la modelo entidad-relación

Apuntes de Bases de Datos by Simón Llinares Riestra is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.