Otra forma (sin Nulos y sin ciclos en las FOREIGN KEY
relaciones) es tener una tercera mesa para almacenar los "hijos favoritos". En la mayoría de los DBMS, necesitará una UNIQUE
restricción adicional TableB
.
@ Aaron fue más rápido al identificar que la convención de nomenclatura anterior es bastante engorrosa y puede provocar errores. Por lo general, es mejor (y lo mantendrá cuerdo) si no tiene Id
columnas en todas sus tablas y si las columnas (que están unidas) tienen los mismos nombres en las muchas tablas que aparecen. Entonces, aquí hay un cambio de nombre:
Parent
ParentID INT NOT NULL PRIMARY KEY
Child
ChildID INT NOT NULL PRIMARY KEY
ParentID INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
UNIQUE (ParentID, ChildID)
FavoriteChild
ParentID INT NOT NULL PRIMARY KEY
ChildID INT NOT NULL
FOREIGN KEY (ParentID, ChildID)
REFERENCES Child (ParentID, ChildID)
En SQL-Server (que está utilizando), también tiene la opción de la IsFavorite
columna de bits que menciona. El niño favorito único por padre se puede lograr a través de un índice único filtrado:
Parent
ParentID INT NOT NULL PRIMARY KEY
Child
ChildID INT NOT NULL PRIMARY KEY
ParentID INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
IsFavorite BIT NOT NULL
CREATE UNIQUE INDEX is_FavoriteChild
ON Child (ParentID)
WHERE IsFavorite = 1 ;
Y la razón principal por la que no se recomienda su opción 1, al menos no en SQL-Server, es que el patrón de rutas circulares en las referencias de clave externa tiene algunos problemas.
Lea un artículo bastante antiguo: SQL By Design: The Circular Reference
Al insertar o eliminar filas de las dos tablas, se encontrará con el problema del "huevo y la gallina". ¿Qué tabla debo insertar primero, sin violar ninguna restricción?
Para resolver eso, debe definir al menos una columna que pueda contener nulos. (OK, técnicamente no tiene que hacerlo, puede tener todas las columnas, NOT NULL
pero solo en DBMS, como Postgres y Oracle, que han implementado restricciones diferibles. Vea la respuesta de @ Erwin en una pregunta similar: restricción de clave externa compleja en SQLAlchemy sobre cómo Esto se puede hacer en Postgres). Aún así, esta configuración se siente como patinar sobre hielo delgado.
Compruebe también una pregunta casi idéntica en SO (pero para MySQL) En SQL, ¿está bien que dos tablas se refieran entre sí? donde mi respuesta es más o menos la misma. Sin embargo, MySQL no tiene índices parciales, por lo que las únicas opciones viables son el FK anulable y la solución de tabla adicional.