No, no está bien. Las referencias circulares entre tablas son desordenadas. Consulte este artículo (de hace una década):SQL By Design:The Circular Reference
Algunos DBMS pueden manejarlos, y con especial cuidado, pero MySQL tendrá problemas.
Opción 1
Como su diseño, para hacer que uno de los dos FK sea anulable. Esto le permite resolver el problema del huevo y la gallina (¿en qué tabla debo insertar primero?).
Sin embargo, hay un problema con su código. ¡Permitirá que un producto tenga una imagen predeterminada donde esa imagen hará referencia a otro producto!
Para rechazar tal error, su restricción FK debe ser:
CONSTRAINT FK_products_1
FOREIGN KEY (id, default_picture_id)
REFERENCES products_pictures (product_id, id)
ON DELETE RESTRICT --- the SET NULL options would
ON UPDATE RESTRICT --- lead to other issues
Esto requerirá un UNIQUE
restricción/índice en la tabla products_pictures
en (product_id, id)
para que el FK anterior se defina y funcione correctamente.
Opción 2
Otro enfoque es eliminar el Default_Picture_ID
columna del product
tabla y agregue un IsDefault BIT
columna en la picture
mesa. El problema con esta solución es cómo permitir que solo una imagen por producto tenga ese bit activado y todas las demás lo tengan desactivado. En SQL-Server (y creo que en Postgres) esto se puede hacer con un índice parcial:
CREATE UNIQUE INDEX is_DefaultPicture
ON products_pictures (Product_ID)
WHERE IsDefault = 1 ;
Pero MySQL no tiene esa característica.
Opción 3
Este enfoque le permite incluso tener ambas columnas FK definidas como NOT NULL
es utilizar restricciones diferibles. Esto funciona en PostgreSQL y creo que en Oracle. Verifique esta pregunta y la respuesta de @Erwin:Restricción de clave externa compleja en SQLAlchemy
(las Todas las columnas clave NO SON NULAS parte).
Las restricciones en MySQL no se pueden diferir.
Opción 4
El enfoque (que encuentro más limpio) es eliminar el Default_Picture_ID
columna y agregue otra tabla. No hay ruta circular en las restricciones FK y todas las columnas FK serán NOT NULL
con esta solución:
product_default_picture
----------------------
product_id NOT NULL
default_picture_id NOT NULL
PRIMARY KEY (product_id)
FOREIGN KEY (product_id, default_picture_id)
REFERENCES products_pictures (product_id, id)
Esto también requerirá un UNIQUE
restricción/índice en la tabla products_pictures
en (product_id, id)
como en la solución 1.
Para resumir, con MySQL tienes dos opciones:
-
opción 1 (una columna FK anulable) con la corrección anterior para hacer cumplir la integridad correctamente
-
opción 4 (sin columnas FK anulables)