Nie, nie jest ok. Okrągłe odniesienia między tabelami są bałaganiarskie. Zobacz ten (dziesięcioletni) artykuł:SQL By Design:The Circular Reference
Niektóre DBMS mogą sobie z tym poradzić i to ze szczególną ostrożnością, ale MySQL będzie miał problemy.
Opcja 1
Jako twój projekt, aby jeden z dwóch FK był nieważny. To pozwala rozwiązać problem z kurczakiem i jajkiem (do której tabeli powinienem najpierw wstawić?).
Jest jednak problem z twoim kodem. Dzięki temu produkt będzie miał domyślne zdjęcie, w którym to zdjęcie będzie odnosić się do innego produktu!
Aby uniemożliwić taki błąd, twoje ograniczenie FK powinno być:
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
Będzie to wymagało UNIQUE
ograniczenie/indeks w tabeli products_pictures
na (product_id, id)
aby powyższe FK było zdefiniowane i działało poprawnie.
Opcja 2
Innym podejściem jest usunięcie Default_Picture_ID
kolumna z product
tabeli i dodaj IsDefault BIT
kolumna w picture
stół. Problem z tym rozwiązaniem polega na tym, aby tylko jedno zdjęcie na produkt miało ten bit, a wszystkie inne go miały. W SQL-Server (a myślę, że w Postgresie) można to zrobić za pomocą częściowego indeksu:
CREATE UNIQUE INDEX is_DefaultPicture
ON products_pictures (Product_ID)
WHERE IsDefault = 1 ;
Ale MySQL nie ma takiej funkcji.
Opcja 3
Takie podejście pozwala nawet mieć obie kolumny FK zdefiniowane jako NOT NULL
jest użycie odroczonych ograniczeń. Działa to w PostgreSQL i myślę, że w Oracle. Sprawdź to pytanie i odpowiedź @Erwin:Złożone ograniczenie klucza obcego w SQLAlchemy
(Wszystkie kluczowe kolumny NOT NULL Część).
Ograniczeń w MySQL nie można odroczyć.
Opcja 4
Podejście (które uważam za najczystsze) polega na usunięciu Default_Picture_ID
kolumnę i dodaj kolejną tabelę. Brak ścieżki kołowej w ograniczeniach FK i wszystkie kolumny FK będą NOT NULL
z tym rozwiązaniem:
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)
Będzie to również wymagało UNIQUE
ograniczenie/indeks w tabeli products_pictures
na (product_id, id)
jak w rozwiązaniu 1.
Podsumowując, w MySQL masz dwie opcje:
-
opcja 1 (kolumna FK dopuszczająca wartość null) z powyższą poprawką w celu poprawnego wymuszenia integralności
-
opcja 4 (bez pustych kolumn FK)