Ne, to není v pořádku. Kruhové odkazy mezi tabulkami jsou chaotické. Podívejte se na tento (dekádu starý) článek:SQL By Design:The Circular Reference
Některé DBMS to zvládnou a se zvláštní péčí, ale MySQL bude mít problémy.
Možnost 1
Jako váš návrh, aby byl jeden ze dvou FK neplatný. To vám umožní vyřešit problém s kuřecím masem a vejci (do které tabulky mám vložit jako první?).
S vaším kódem je však problém. To umožní produktu mít výchozí obrázek, kde tento obrázek bude odkazovat na jiný produkt!
Chcete-li takovou chybu zakázat, vaše omezení FK by mělo být:
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
To bude vyžadovat UNIQUE
omezení/index v tabulce products_pictures
na (product_id, id)
aby výše uvedené FK byly definovány a správně fungovaly.
Možnost 2
Dalším způsobem je odstranění Default_Picture_ID
ze sloupce product
tabulku a přidejte IsDefault BIT
ve sloupci picture
stůl. Problém s tímto řešením je, jak povolit pouze jednomu obrázku na produkt, aby měl tento bit zapnutý, a všem ostatním jej mít vypnutý. V SQL-Serveru (a myslím, že v Postgresu) to lze provést pomocí částečného indexu:
CREATE UNIQUE INDEX is_DefaultPicture
ON products_pictures (Product_ID)
WHERE IsDefault = 1 ;
MySQL však žádnou takovou funkci nemá.
Možnost 3
Tento přístup vám dokonce umožňuje mít oba sloupce FK definované jako NOT NULL
je použití odložitelných omezení. Toto funguje v PostgreSQL a myslím, že v Oracle. Zkontrolujte tuto otázku a odpověď od @Erwin:Komplexní omezení cizího klíče v SQLAlchemy
(Všechny klíčové sloupce NOT NULL Část).
Omezení v MySQL nelze odložit.
Možnost 4
Přístup (který považuji za nejčistší) je odstranit Default_Picture_ID
sloupec a přidejte další tabulku. Žádná kruhová cesta ve vazbách FK a všechny sloupce FK budou NOT NULL
s tímto řešením:
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)
To bude také vyžadovat UNIQUE
omezení/index v tabulce products_pictures
na (product_id, id)
jako v řešení 1.
Abych to shrnul, s MySQL máte dvě možnosti:
-
možnost 1 (sloupec FK s možnou hodnotou null) s výše uvedenou opravou pro správné vynucení integrity
-
možnost 4 (žádné sloupce FK s možnou hodnotou null)