No, non va bene. I riferimenti circolari tra le tabelle sono disordinati. Vedi questo articolo (vecchio di decenni):SQL By Design:The Circular Reference
Alcuni DBMS possono gestirli, e con particolare attenzione, ma MySQL avrà problemi.
Opzione 1
Come tuo progetto, per rendere nullable uno dei due FK. Questo ti permette di risolvere il problema dell'uovo e della gallina (in quale tabella devo prima inserire?).
C'è un problema però con il tuo codice. Consentirà a un prodotto di avere un'immagine predefinita in cui quell'immagine farà riferimento a un altro prodotto!
Per non consentire un tale errore, il tuo vincolo FK dovrebbe essere:
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
Ciò richiederà un UNIQUE
vincolo/indice nella tabella products_pictures
su (product_id, id)
affinché l'FK di cui sopra sia definito e funzioni correttamente.
Opzione 2
Un altro approccio consiste nel rimuovere il Default_Picture_ID
colonna forma il product
tabella e aggiungi un IsDefault BIT
colonna nella picture
tavolo. Il problema con questa soluzione è come consentire a una sola immagine per prodotto di avere quel bit e a tutti gli altri di averlo spento. In SQL-Server (e penso in Postgres) questo può essere fatto con un indice parziale:
CREATE UNIQUE INDEX is_DefaultPicture
ON products_pictures (Product_ID)
WHERE IsDefault = 1 ;
Ma MySQL non ha tale funzionalità.
Opzione 3
Questo approccio ti consente anche di avere entrambe le colonne FK definite come NOT NULL
consiste nell'utilizzare vincoli differibili. Funziona in PostgreSQL e penso in Oracle. Controlla questa domanda e la risposta di @Erwin:Vincolo di chiave esterna complesso in SQLAlchemy
(le Tutte le colonne chiave NON NULL parte).
I vincoli in MySQL non possono essere rinviati.
Opzione 4
L'approccio (che trovo più pulito) è rimuovere il Default_Picture_ID
colonna e aggiungi un'altra tabella. Nessun percorso circolare nei vincoli FK e tutte le colonne FK saranno NOT NULL
con questa soluzione:
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)
Ciò richiederà anche un UNIQUE
vincolo/indice nella tabella products_pictures
su (product_id, id)
come nella soluzione 1.
Per riassumere, con MySQL hai due opzioni:
-
opzione 1 (una colonna FK nullable) con la correzione sopra per applicare correttamente l'integrità
-
opzione 4 (nessuna colonna FK nullable)