Digamos que tengo el siguiente diagrama ER:
Ahora, si representé la relación usando una clave foránea de School
in Student
, podría tener NULL
valores (porque a Student
no se requiere que pertenezca a a School
), por ejemplo:
Entonces, la forma correcta (según lo que he leído) es crear una tabla de intersección para representar la relación, por ejemplo:
De esta manera, no NULL
puede haber valores presentes en la tabla School_has_Student
.
Pero, ¿cuáles son las desventajas de usar una clave externa anulable en lugar de crear una tabla de intersección?
Editar:
Elegí por error ( school_id
, student_id
) ser la clave principal de la School_has_Student
tabla, lo que hizo que la relación fuera de muchos a muchos. La clave primaria correcta debería haber sido student_id
:
Respuestas:
Los dos modelos representan relaciones diferentes.
Al usar una tabla de unión, está modelando una relación de muchos a muchos.
Al utilizar una clave externa simple, está modelando una relación uno a muchos.
La desventaja de una clave externa anulable es que no puede modelar la relación como muchos a muchos, si eso es lo que está tratando de lograr.
Según su edición de la pregunta, está dividiendo efectivamente la tabla del alumno en dos tablas con la misma clave. Generalmente veo esto en tablas que tienen demasiados campos, por lo que alguien los divide en dos para ser más manejables (lo llamo poner lápiz labial en un cerdo).
Al dividir la tabla del alumno, está haciendo que la segunda tabla sea opcional porque no es necesario que exista un registro en la segunda tabla. Lo cual es muy similar a un campo que no necesita ser configurado porque puede ser nulo.
Si desea una relación de uno a muchos, es mucho mejor usar una sola tabla y permitir que la identificación de la escuela sea nula en la tabla del estudiante. No hay razón para evitar nulos en los campos, incluso para una clave foránea. Eso significa que la relación externa es opcional: los desarrolladores y los DBA lo entienden claramente, y el motor de base de datos subyacente ciertamente debería funcionar bien.
Si le preocupan las uniones, no se preocupe. Hay una semántica bien definida sobre cómo funcionan las uniones con campos nulos. Al usar una sola tabla, puede unir dos tablas en lugar de tres.
fuente
NULL
valores?student_id
una clave principal en laSchool_has_Student
tabla, que mantuvo la relación como uno a muchos. ¿Qué inconvenientes tiene este método sobre el uso de una clave externa?Escribiste en un comentario arriba:
Cuando hay muchos valores NULL en la columna de clave externa, sus programas tendrán que lidiar con esta columna en su mayoría vacía para cada registro que procesen. La columna probablemente ocupará algo de espacio en el disco, aunque en el 98% de los casos esté vacía, consultar la relación significa consultar esa columna que le brinda más tráfico de red, y si está utilizando un ORM que genera clases a partir de sus tablas, sus programas También necesitará más espacio del lado del cliente de lo necesario. El uso de una tabla de intersección evita esto, solo habrá registros de enlaces necesarios donde la clave externa equivalente no sería NULL de lo contrario.
Opuesto a eso, si no tiene solo unos pocos valores NULL, digamos que el 50% o más de las relaciones no son NULL, el uso de una tabla de intersección le da el efecto contrario: más espacio en disco, mayor complejidad que resulta en más tráfico de red, etc.
Por lo tanto, el uso de una tabla de intersección es solo una forma de optimización, solo sensible para un caso específico, y especialmente hoy en día, donde el espacio en disco y la memoria se volvieron más baratos, mucho menos necesarios. Tenga en cuenta que "Fundamentos de los sistemas de bases de datos" se escribió originalmente hace más de 20 años (encontré una referencia a la segunda edición de 1994), y supongo que esa recomendación ya estaba allí en ese momento. Antes de 1994, la optimización del espacio era probablemente mucho más importante que hoy, ya que el almacenamiento masivo era aún más costoso y las computadoras y las redes eran mucho más lentas que hoy.
Como nota al margen de un comentario exigente: la declaración anterior solo está tratando de anticipar lo que el autor de "Fundamentos de los sistemas de bases de datos" tenía en mente con su recomendación, supongo que estaba haciendo una declaración general, válida para la mayoría de los sistemas. En algunas bases de datos hay otras optimizaciones posibles como "columnas dispersas" que hacen que el uso de una tabla de intersección sea aún más obsoleto.
Así que no te equivoques con esa recomendación. El libro no le dice que prefiera las tablas de intersección para las
{0,1}:n
relaciones en general, o, como escribió, que esta es la "forma correcta". Utilice optimizaciones como esta que harán que sus programas sean más complicados solo cuando realmente los necesite.fuente
El modelo conceptual se verá así, lo cual es muy poco ortodoxo por decir lo menos:
El modelo físico se verá así, lo cual es confuso por decir lo menos (las personas pensarán que es M: M a menos que vean de cerca):
Mi sugerencia:
Si tiene muchas columnas (FK o de otro tipo) que no se aplican a la mayoría de los estudiantes, separe las tablas en tablas de roles con valores 1: 1. Pero eso no es porque sean FK, es porque las columnas no se aplican a la mayoría de las filas.
De lo contrario , los FK anulables son una parte normal de una base de datos y las tablas de unión suelen ser para M: M rels.
Los usos comunes de los archivos 1: 1 son para tablas de roles que tienen columnas que se aplican solo si la entidad es de cierto tipo, y extraen columnas BLOB por consideraciones de rendimiento o almacenamiento. Evitar valores nulos en FK no es un uso común para eso.
fuente
Además de otras respuestas, me gustaría señalar que un valor nulo para la clave externa es ambiguo. Eso significa:
1) La escuela del alumno (si la hay) es desconocida (este es el significado estándar de 'nulo' - el valor es desconocido)
2) Se sabe si el estudiante tiene o no una escuela y no tiene ninguna.
Si usa el significado estándar de nulo, ¿cómo representaría "estudiante no tiene escuela" en su modelo de clave extranjera. En ese caso, probablemente tenga que crear una entrada "sin escuela", con su propia identificación en la tabla de la escuela. (No es ideal)
fuente
NULL
, puede significar: 1) Valor desconocido. 2) Valor no disponible o retenido. 3) Atributo no aplicable (creo que esta interpretación significa que puede especificar aNULL
para una clave foránea).Las tablas de la base de datos tienen esta cosa agradable llamada restricciones. Por lo tanto, es muy fácil hacer una tabla de intersección que permite que solo 1 de cada estudiante aparezca en la tabla, pero muchas escuelas en esa tabla. Efectivamente dándote un
La teoría es buena, pero al final modelarás tu base de datos después de las preguntas que haces.
Si desea hacer preguntas a menudo con la pregunta: "qué estudiantes están en mi escuela", ¿realmente desea consultar la tabla completa de estudiantes o tener una tabla de intersección fácil?
En bases de datos: optimice las preguntas que haga.
fuente
Hay un caso de uso en el que usar una tercera tabla puede tener sentido. El ejemplo puede parecer puramente hipotético, pero espero que ilustre bien mi punto. Supongamos que agrega más columnas a la
students
tabla y, en algún momento, decide imponer la unicidad en los registros a través del índice compuesto en varias columnas. Es muy probable que también tengas que incluir laschool_id
columna, y aquí las cosas comienzan a complicarse. Debido a la forma en que fue diseñado SQL, insertar varios registros idénticos dondeschool_id
estáNULL
será posible. Tiene mucho sentido desde una perspectiva técnica, pero es contradictorio y puede conducir a resultados inesperados. Por otro lado, hacer cumplir la unicidad en la tabla de intersección es fácil.Tuve que modelar una relación "opcional" recientemente, donde el requisito de una restricción de unicidad se debía a una columna de marca de tiempo. Dejar la clave foránea anulable en la tabla de repente conduce a la posibilidad de insertar registros con la misma marca de tiempo (supongamos que es una predeterminada, establecida en registros que aún no han sido auditados / aprobados), y la única salida era eliminar columna anulable.
Como puede ver, es un caso bastante específico y, como otros lo notaron, la mayoría de las veces estaría perfectamente bien con todos los
NULL
valores. Realmente depende de los requisitos específicos de su modelo.fuente
Además de las muchas buenas sugerencias ya presentadas, personalmente no soy fanático de las claves externas a menos que sean realmente necesarias. Primero está la relación M: M a la que hace referencia. Además, llamar a una clave externa y, por lo tanto, incorporar los datos de esa tabla en sus consultas, introduce más complejidad y, según el tamaño de la tabla, un rendimiento más lento. Como otros han dicho, los campos FK anulables pueden no ser compatibles y pueden crear problemas de integridad de datos.
Si está definiendo un estado donde la escuela estudiantil es desconocida o está vacía, el NULL no diferenciará esas condiciones. (una vez más, volvemos a la integridad de los datos). La sugerencia de tabla de roles de Tulains es elegante y permite valores nulos de forma clara.
fuente