Nee, het is niet oke. Cirkelverwijzingen tussen tabellen zijn rommelig. Zie dit (tien jaar oud) artikel:SQL By Design:The Circular Reference
Sommige DBMS kunnen hiermee omgaan, en met speciale zorg, maar MySQL zal problemen hebben.
Optie 1
Als jouw ontwerp, om een van de twee FK's nullable te maken. Hiermee kun je het kip-en-ei-probleem oplossen (in welke tabel moet ik het eerst invoegen?).
Er is echter een probleem met uw code. Hierdoor kan een product een standaardafbeelding hebben waar die afbeelding naar een ander product verwijst!
Om een dergelijke fout niet toe te staan, moet uw FK-beperking zijn:
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
Dit vereist een UNIQUE
beperking/index in tabel products_pictures
op (product_id, id)
om de bovenstaande FK te definiëren en correct te laten werken.
Optie 2
Een andere benadering is het verwijderen van de Default_Picture_ID
kolom uit het product
tabel en voeg een IsDefault BIT
toe kolom in de picture
tafel. Het probleem met deze oplossing is hoe je slechts één foto per product toestaat om dat bit aan te hebben en alle anderen om het uit te hebben. In SQL-Server (en ik denk in Postgres) kan dit met een gedeeltelijke index:
CREATE UNIQUE INDEX is_DefaultPicture
ON products_pictures (Product_ID)
WHERE IsDefault = 1 ;
Maar MySQL heeft zo'n functie niet.
Optie 3
Met deze aanpak kunt u zelfs beide FK-kolommen definiëren als NOT NULL
is om uitstelbare beperkingen te gebruiken. Dit werkt in PostgreSQL en ik denk in Oracle. Controleer deze vraag en het antwoord van @Erwin:Complexe externe sleutelbeperking in SQLAlchemy
(de Alle sleutelkolommen NIET NULL deel).
Beperkingen in MySQL kunnen niet worden uitgesteld.
Optie 4
De aanpak (die ik het schoonst vind) is om de Default_Picture_ID
. te verwijderen kolom en voeg nog een tabel toe. Geen cirkelvormig pad in de FK-beperkingen en alle FK-kolommen zijn NOT NULL
met deze oplossing:
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)
Dit vereist ook een UNIQUE
beperking/index in tabel products_pictures
op (product_id, id)
zoals in oplossing 1.
Om samen te vatten, met MySQL heb je twee opties:
-
optie 1 (een nullable FK-kolom) met de bovenstaande correctie om integriteit correct af te dwingen
-
optie 4 (geen nullable FK-kolommen)